check for <application android:testOnly="true">

This adds a check for "testOnly" to the existing "debuggable" check, since
they are very similar.  We should really be refactoring all the checks into
a more reasonable setup.  Since "debuggable" and "testOnly" are both set in
the same place (`<application>` in _AndroidManifest.xml_) and are both set
by the same process (running debug builds), I thought it would be OK to
include both in the same place.  Plus it was a one-line change.
This commit is contained in:
Hans-Christoph Steiner 2024-04-01 12:40:14 +02:00 committed by Michael Pöhn
parent 0cf1749ec3
commit 9c65bed4a5
6 changed files with 26 additions and 16 deletions

View File

@ -720,8 +720,10 @@ def build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, ext
f"{app.id}:{build.versionName}", p.output)
# Make sure it's not debuggable...
if common.is_apk_and_debuggable(src):
raise BuildException("APK is debuggable")
if common.is_debuggable_or_testOnly(src):
raise BuildException(
"%s: debuggable or testOnly set in AndroidManifest.xml" % src
)
# By way of a sanity check, make sure the version and version
# code in our new APK match what we expect...

View File

@ -2677,10 +2677,13 @@ def ensure_final_value(packageName, arsc, value):
return ''
def is_apk_and_debuggable(apkfile):
"""Return True if the given file is an APK and is debuggable.
def is_debuggable_or_testOnly(apkfile):
"""Return True if the given file is an APK and is debuggable or testOnly.
Parse only <application android:debuggable=""> from the APK.
These two settings should never be enabled in release builds. This
parses <application android:debuggable="" android:testOnly="">
from the APK and nothing else to run fast, since it is run on
every APK as part of update.
Parameters
----------
@ -2699,7 +2702,7 @@ def is_apk_and_debuggable(apkfile):
if _type == START_TAG and axml.getName() == 'application':
for i in range(0, axml.getAttributeCount()):
name = axml.getAttributeName(i)
if name == 'debuggable':
if name in ('debuggable', 'testOnly'):
_type = axml.getAttributeValueType(i)
_data = axml.getAttributeValueData(i)
value = format_value(_type, _data, lambda _: axml.getAttributeValue(i))

View File

@ -1616,8 +1616,10 @@ def process_apk(apkcache, apkfilename, repodir, knownapks, use_date_from_apk=Fal
return True, None, False
# Check for debuggable apks...
if common.is_apk_and_debuggable(apkfile):
logging.warning('{0} is set to android:debuggable="true"'.format(apkfile))
if common.is_debuggable_or_testOnly(apkfile):
logging.warning(
"%s: debuggable or testOnly set in AndroidManifest.xml" % apkfile
)
if options.rename_apks:
n = apk['packageName'] + '_' + str(apk['versionCode']) + '.apk'

View File

@ -221,7 +221,7 @@ class BuildTest(unittest.TestCase):
@mock.patch('fdroidserver.common.get_apk_id')
@mock.patch('fdroidserver.build.FDroidPopen')
@mock.patch('fdroidserver.common.is_apk_and_debuggable', lambda f: False)
@mock.patch('fdroidserver.common.is_debuggable_or_testOnly', lambda f: False)
@mock.patch('fdroidserver.common.get_native_code', lambda f: 'x86')
def test_build_local_maven(self, fake_FDroidPopen, fake_get_apk_id):
"""Test build_local() with a maven project"""
@ -342,7 +342,8 @@ class BuildTest(unittest.TestCase):
'fdroidserver.common.sha256sum',
return_value='ad7ce5467e18d40050dc51b8e7affc3e635c85bd8c59be62de32352328ed467e',
) as _ignored, mock.patch(
'fdroidserver.common.is_apk_and_debuggable', return_value=False
'fdroidserver.common.is_debuggable_or_testOnly',
return_value=False,
) as _ignored, mock.patch(
'fdroidserver.build.FDroidPopen', FakeProcess
) as _ignored, mock.patch(
@ -394,7 +395,7 @@ class BuildTest(unittest.TestCase):
@mock.patch('sdkmanager.build_package_list', lambda use_net: None)
@mock.patch('fdroidserver.build.FDroidPopen', FakeProcess)
@mock.patch('fdroidserver.common.get_native_code', lambda _ignored: 'x86')
@mock.patch('fdroidserver.common.is_apk_and_debuggable', lambda _ignored: False)
@mock.patch('fdroidserver.common.is_debuggable_or_testOnly', lambda _ignored: False)
@mock.patch(
'fdroidserver.common.sha256sum',
lambda f: 'ad7ce5467e18d40050dc51b8e7affc3e635c85bd8c59be62de32352328ed467e',
@ -531,7 +532,8 @@ class BuildTest(unittest.TestCase):
return_value=(app.id, build.versionCode, build.versionName),
):
with mock.patch(
'fdroidserver.common.is_apk_and_debuggable', return_value=False
'fdroidserver.common.is_debuggable_or_testOnly',
return_value=False,
):
fdroidserver.build.build_local(
app,

View File

@ -185,7 +185,7 @@ class CommonTest(unittest.TestCase):
fdroidserver.common._add_java_paths_to_config(pathlist, config)
self.assertEqual(config['java_paths']['8'], choice[1:])
def test_is_apk_and_debuggable(self):
def test_is_debuggable_or_testOnly(self):
config = dict()
fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config
@ -197,7 +197,7 @@ class CommonTest(unittest.TestCase):
testfiles.append(os.path.join(self.basedir, 'urzip-badcert.apk'))
for apkfile in testfiles:
self.assertTrue(
fdroidserver.common.is_apk_and_debuggable(apkfile),
fdroidserver.common.is_debuggable_or_testOnly(apkfile),
"debuggable APK state was not properly parsed!",
)
@ -208,7 +208,7 @@ class CommonTest(unittest.TestCase):
testfiles.append(os.path.join(self.basedir, 'v2.only.sig_2.apk'))
for apkfile in testfiles:
self.assertFalse(
fdroidserver.common.is_apk_and_debuggable(apkfile),
fdroidserver.common.is_debuggable_or_testOnly(apkfile),
"debuggable APK state was not properly parsed!",
)

View File

@ -276,7 +276,8 @@ class ScannerTest(unittest.TestCase):
return_value=(app.id, build.versionCode, build.versionName),
):
with mock.patch(
'fdroidserver.common.is_apk_and_debuggable', return_value=False
'fdroidserver.common.is_debuggable_or_testOnly',
return_value=False,
):
fdroidserver.build.build_local(
app,