android: Improve workflow on devices with root

During initial scan of application, detect if root access is available
and track it.  If user later selects "Click here for ways to fix this".
display a new dialogue that offers to push the layer directly.

If pushing fails, fall back to production dialogue.

Also add a new persistent setting to enable automatic layer pushing.
This commit is contained in:
Cody Northrop
2017-08-07 14:41:36 -06:00
committed by Baldur Karlsson
parent 6c40e4e651
commit fb8eef23d0
8 changed files with 149 additions and 11 deletions
@@ -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))
@@ -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
+97 -9
View File
@@ -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("<b>Missing library</b><br>"
"The RenderDoc library must be present in the "
"installed application.<br><br>"
"To fix this, you should repackage the APK following guidelines on the "
"<a href='http://github.com/baldurk/renderdoc/wiki/Android-Support'>"
"RenderDoc Wiki</a><br><br>");
"installed application.<br><br>");
}
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 <b>root access</b>. If you are only targeting Vulkan, "
"RenderDoc can try to push the layer directly to your application.<br><br>"
"Would you like RenderDoc to push the layer?<br>");
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.<br><br>"));
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 "
"<a href='http://github.com/baldurk/renderdoc/wiki/Android-Support'>"
"RenderDoc Wiki</a><br><br>"
"If you are only targeting Vulkan, RenderDoc can try to <b>add the layer for you</b>, "
"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()
"</a> to get them.<br><br>"
"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)
{
@@ -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();
}
@@ -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);
+20 -1
View File
@@ -874,7 +874,7 @@ If {spv_disas} is not used, the tool is expected to output the disassembly on st
</property>
</widget>
</item>
<item row="3" column="0">
<item row="4" column="0">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -887,6 +887,25 @@ If {spv_disas} is not used, the tool is expected to output the disassembly on st
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_26">
<property name="toolTip">
<string>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.</string>
</property>
<property name="text">
<string>Automatically push RenderDoc layer for Vulkan on devices with root access.</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="Android_AutoPushLayerToApp">
<property name="toolTip">
<string>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.</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_25">
<property name="toolTip">
+6 -1
View File
@@ -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);
+6
View File
@@ -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;
}