[Android] Set permission when installing apks.

To support M testing, we need to explicilty grant permissions to apps
when we install them.

BUG=

Review URL: https://codereview.chromium.org/1316803004

Cr-Original-Commit-Position: refs/heads/master@{#347787}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: de468d72d9eeeb86b439e6a7c877de0ebb349fca
This commit is contained in:
rnephew 2015-09-08 14:03:01 -07:00 коммит произвёл Commit bot
Родитель f536e96df0
Коммит f526e23829
9 изменённых файлов: 163 добавлений и 34 удалений

Просмотреть файл

@ -110,6 +110,13 @@ class ApkHelper(object):
return self._package_name
raise Exception('Failed to determine package name of %s' % self._apk_path)
def GetPermissions(self):
manifest_info = self._GetManifest()
try:
return manifest_info['manifest']['uses-permission']['android:name']
except KeyError:
return []
def GetSplitName(self):
"""Returns the name of the split of the apk."""
if self._split_name:

Просмотреть файл

@ -51,30 +51,6 @@ _DEFAULT_RETRIES = 3
# the timeout_retry decorators.
DEFAULT = object()
_CONTROL_CHARGING_COMMANDS = [
{
# Nexus 4
'witness_file': '/sys/module/pm8921_charger/parameters/disabled',
'enable_command': 'echo 0 > /sys/module/pm8921_charger/parameters/disabled',
'disable_command':
'echo 1 > /sys/module/pm8921_charger/parameters/disabled',
},
{
# Nexus 5
# Setting the HIZ bit of the bq24192 causes the charger to actually ignore
# energy coming from USB. Setting the power_supply offline just updates the
# Android system to reflect that.
'witness_file': '/sys/kernel/debug/bq24192/INPUT_SRC_CONT',
'enable_command': (
'echo 0x4A > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
'echo 1 > /sys/class/power_supply/usb/online'),
'disable_command': (
'echo 0xCA > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
'chmod 644 /sys/class/power_supply/usb/online && '
'echo 0 > /sys/class/power_supply/usb/online'),
},
]
_RESTART_ADBD_SCRIPT = """
trap '' HUP
trap '' TERM
@ -86,6 +62,34 @@ _RESTART_ADBD_SCRIPT = """
restart &
"""
# Not all permissions can be set.
_PERMISSIONS_BLACKLIST = [
'android.permission.ACCESS_MOCK_LOCATION',
'android.permission.ACCESS_NETWORK_STATE',
'android.permission.BLUETOOTH',
'android.permission.BLUETOOTH_ADMIN',
'android.permission.INTERNET',
'android.permission.MANAGE_ACCOUNTS',
'android.permission.MODIFY_AUDIO_SETTINGS',
'android.permission.NFC',
'android.permission.READ_SYNC_SETTINGS',
'android.permission.READ_SYNC_STATS',
'android.permission.USE_CREDENTIALS',
'android.permission.VIBRATE',
'android.permission.WAKE_LOCK',
'android.permission.WRITE_SYNC_SETTINGS',
'com.android.browser.permission.READ_HISTORY_BOOKMARKS',
'com.android.browser.permission.WRITE_HISTORY_BOOKMARKS',
'com.android.launcher.permission.INSTALL_SHORTCUT',
'com.chrome.permission.DEVICE_EXTRAS',
'com.google.android.apps.chrome.permission.C2D_MESSAGE',
'com.google.android.apps.chrome.permission.READ_WRITE_BOOKMARK_FOLDERS',
'com.google.android.apps.chrome.TOS_ACKED',
'com.google.android.c2dm.permission.RECEIVE',
'com.google.android.providers.gsf.permission.READ_GSERVICES',
'com.sec.enterprise.knox.MDM_CONTENT_PROVIDER',
]
_CURRENT_FOCUS_CRASH_RE = re.compile(
r'\s*mCurrentFocus.*Application (Error|Not Responding): (\S+)}')
@ -515,13 +519,16 @@ class DeviceUtils(object):
@decorators.WithTimeoutAndRetriesDefaults(
INSTALL_DEFAULT_TIMEOUT,
INSTALL_DEFAULT_RETRIES)
def Install(self, apk_path, reinstall=False, timeout=None, retries=None):
def Install(self, apk_path, reinstall=False, permissions=None, timeout=None,
retries=None):
"""Install an APK.
Noop if an identical APK is already installed.
Args:
apk_path: A string containing the path to the APK to install.
permissions: Set of permissions to set. If not set, finds permissions with
apk helper. To set no permissions, pass [].
reinstall: A boolean indicating if we should keep any existing app data.
timeout: timeout in seconds
retries: number of retries
@ -553,6 +560,12 @@ class DeviceUtils(object):
self.adb.Install(apk_path, reinstall=reinstall)
self._cache['package_apk_checksums'][package_name] = host_checksums
if (permissions is None
and self.build_version_sdk >= version_codes.MARSHMALLOW):
permissions = apk_helper.ApkHelper(apk_path).GetPermissions()
self.GrantPermissions(package_name, permissions)
@decorators.WithTimeoutAndRetriesDefaults(
INSTALL_DEFAULT_TIMEOUT,
INSTALL_DEFAULT_RETRIES)
@ -1940,3 +1953,24 @@ class DeviceUtils(object):
self.WriteFile(script.name, _RESTART_ADBD_SCRIPT)
self.RunShellCommand(['source', script.name], as_root=True)
self.adb.WaitForDevice()
@decorators.WithTimeoutAndRetriesFromInstance()
def GrantPermissions(self, package, permissions, timeout=None, retries=None):
# Permissions only need to be set on M and above because of the changes to
# the permission model.
if not permissions or self.build_version_sdk < version_codes.MARSHMALLOW:
return
# TODO(rnephew): After permission blacklist is complete, switch to using
# &&s instead of ;s.
cmd = ''
logging.info('Setting permissions for %s', package)
for p in permissions:
if p not in _PERMISSIONS_BLACKLIST:
cmd += 'pm grant %s %s;' % (package, p)
logging.info(' %s', p)
if cmd:
output = self.RunShellCommand(cmd)
if output:
logging.warning('Possible problem when granting permissions. Blacklist '
'may need to be updated.')
logging.warning(output)

Просмотреть файл

@ -548,13 +548,51 @@ class DeviceUtilsRebootTest(DeviceUtilsTest):
class DeviceUtilsInstallTest(DeviceUtilsTest):
def testInstall_noPriorInstall(self):
with self.patch_call(self.call.device.build_version_sdk, return_value=23):
with self.assertCalls(
(mock.call.devil.android.apk_helper.GetPackageName(
'/fake/test/app.apk'),
'test.package'),
(self.call.device._GetApplicationPathsInternal('test.package'), []),
self.call.adb.Install('/fake/test/app.apk', reinstall=False),
(mock.call.devil.android.apk_helper.ApkHelper.GetPermissions(),
['p1']),
(self.call.device.GrantPermissions('test.package', ['p1']), [])):
self.device.Install('/fake/test/app.apk', retries=0)
def testIntsall_permissionsPreM(self):
with self.patch_call(self.call.device.build_version_sdk, return_value=20):
with self.assertCalls(
(mock.call.devil.android.apk_helper.GetPackageName(
'/fake/test/app.apk'),
'test.package'),
(self.call.device._GetApplicationPathsInternal('test.package'), []),
(self.call.adb.Install('/fake/test/app.apk', reinstall=False))):
self.device.Install('/fake/test/app.apk', retries=0)
def testInstall_findPermissions(self):
with self.patch_call(self.call.device.build_version_sdk, return_value=23):
with self.assertCalls(
(mock.call.devil.android.apk_helper.GetPackageName(
'/fake/test/app.apk'),
'test.package'),
(self.call.device._GetApplicationPathsInternal('test.package'), []),
(self.call.adb.Install('/fake/test/app.apk', reinstall=False)),
(mock.call.devil.android.apk_helper.ApkHelper.GetPermissions(),
['p1']),
(self.call.device.GrantPermissions('test.package', ['p1']), [])):
self.device.Install('/fake/test/app.apk', retries=0)
def testInstall_passPermissions(self):
with self.assertCalls(
(mock.call.devil.android.apk_helper.GetPackageName(
'/fake/test/app.apk'),
'test.package'),
(self.call.device._GetApplicationPathsInternal('test.package'), []),
self.call.adb.Install('/fake/test/app.apk', reinstall=False)):
self.device.Install('/fake/test/app.apk', retries=0)
(self.call.adb.Install('/fake/test/app.apk', reinstall=False)),
(self.call.device.GrantPermissions('test.package', ['p1', 'p2']), [])):
self.device.Install(
'/fake/test/app.apk', retries=0, permissions=['p1', 'p2'])
def testInstall_differentPriorInstall(self):
with self.assertCalls(
@ -568,7 +606,7 @@ class DeviceUtilsInstallTest(DeviceUtilsTest):
(['/fake/test/app.apk'], None)),
self.call.adb.Uninstall('test.package', False),
self.call.adb.Install('/fake/test/app.apk', reinstall=False)):
self.device.Install('/fake/test/app.apk', retries=0)
self.device.Install('/fake/test/app.apk', retries=0, permissions=[])
def testInstall_differentPriorInstall_reinstall(self):
with self.assertCalls(
@ -581,7 +619,8 @@ class DeviceUtilsInstallTest(DeviceUtilsTest):
['/fake/test/app.apk']),
(['/fake/test/app.apk'], None)),
self.call.adb.Install('/fake/test/app.apk', reinstall=True)):
self.device.Install('/fake/test/app.apk', reinstall=True, retries=0)
self.device.Install(
'/fake/test/app.apk', reinstall=True, retries=0, permissions=[])
def testInstall_identicalPriorInstall(self):
with self.assertCalls(
@ -593,7 +632,7 @@ class DeviceUtilsInstallTest(DeviceUtilsTest):
(self.call.device._ComputeStaleApks('test.package',
['/fake/test/app.apk']),
([], None))):
self.device.Install('/fake/test/app.apk', retries=0)
self.device.Install('/fake/test/app.apk', retries=0, permissions=[])
def testInstall_fails(self):
with self.assertCalls(
@ -2014,6 +2053,33 @@ class DeviceUtilsRestartAdbdTest(DeviceUtilsTest):
self.device.RestartAdbd()
class DeviceUtilsGrantPermissionsTest(DeviceUtilsTest):
def testGrantPermissions_none(self):
self.device.GrantPermissions('package', [])
def testGrantPermissions_underM(self):
with self.patch_call(self.call.device.build_version_sdk,
return_value=20):
self.device.GrantPermissions('package', ['p1'])
def testGrantPermissions_one(self):
permissions_cmd = 'pm grant package p1;'
with self.patch_call(self.call.device.build_version_sdk,
return_value=23):
with self.assertCalls(
(self.call.device.RunShellCommand(permissions_cmd), [])):
self.device.GrantPermissions('package', ['p1'])
def testGrantPermissions_multiple(self):
permissions_cmd = 'pm grant package p1;pm grant package p2;'
with self.patch_call(self.call.device.build_version_sdk,
return_value=23):
with self.assertCalls(
(self.call.device.RunShellCommand(permissions_cmd), [])):
self.device.GrantPermissions('package', ['p1', 'p2'])
if __name__ == '__main__':
logging.getLogger().setLevel(logging.DEBUG)
unittest.main(verbosity=2)

Просмотреть файл

@ -144,6 +144,7 @@ class GtestTestInstance(test_instance.TestInstance):
self._activity = helper.GetActivityName()
self._package = helper.GetPackageName()
self._runner = helper.GetInstrumentationName()
self._permissions = helper.GetPermissions()
self._extras = {
_EXTRA_NATIVE_TEST_ACTIVITY: self._activity,
}
@ -319,6 +320,10 @@ class GtestTestInstance(test_instance.TestInstance):
def package(self):
return self._package
@property
def permissions(self):
return self._permissions
@property
def runner(self):
return self._runner

Просмотреть файл

@ -55,12 +55,13 @@ class _ApkDelegate(object):
self._apk = test_instance.apk
self._package = test_instance.package
self._runner = test_instance.runner
self._permissions = test_instance.permissions
self._component = '%s/%s' % (self._package, self._runner)
self._extras = test_instance.extras
def Install(self, device):
device.Install(self._apk)
device.Install(self._apk, permissions=self._permissions)
def Run(self, test, device, flags=None, **kwargs):
extras = dict(self._extras)

Просмотреть файл

@ -15,6 +15,7 @@ from pylib.base import base_test_runner
from pylib.local import local_test_server_spawner
from pylib.perf import perf_control
# Test case statuses.
RE_RUN = re.compile('\\[ RUN \\] ?(.*)\r\n')
RE_FAIL = re.compile('\\[ FAILED \\] ?(.*?)( \\((\\d+) ms\\))?\r\r\n')

Просмотреть файл

@ -138,11 +138,13 @@ class InstrumentationTestInstance(test_instance.TestInstance):
super(InstrumentationTestInstance, self).__init__()
self._apk_under_test = None
self._apk_under_test_permissions = None
self._package_info = None
self._suite = None
self._test_apk = None
self._test_jar = None
self._test_package = None
self._test_permissions = None
self._test_runner = None
self._test_support_apk = None
self._initializeApkAttributes(args, error_func)
@ -178,6 +180,9 @@ class InstrumentationTestInstance(test_instance.TestInstance):
if not os.path.exists(self._apk_under_test):
error_func('Unable to find APK under test: %s' % self._apk_under_test)
apk = apk_helper.ApkHelper(self._apk_under_test)
self._apk_under_test_permissions = apk.GetPermissions()
if args.test_apk.endswith('.apk'):
self._suite = os.path.splitext(os.path.basename(args.test_apk))[0]
self._test_apk = args.test_apk
@ -201,6 +206,7 @@ class InstrumentationTestInstance(test_instance.TestInstance):
apk = apk_helper.ApkHelper(self.test_apk)
self._test_package = apk.GetPackageName()
self._test_permissions = apk.GetPermissions()
self._test_runner = apk.GetInstrumentationName()
self._package_info = None
@ -283,6 +289,10 @@ class InstrumentationTestInstance(test_instance.TestInstance):
def apk_under_test(self):
return self._apk_under_test
@property
def apk_under_test_permissions(self):
return self._apk_under_test_permissions
@property
def flags(self):
return self._flags
@ -323,6 +333,10 @@ class InstrumentationTestInstance(test_instance.TestInstance):
def test_package(self):
return self._test_package
@property
def test_permissions(self):
return self._test_permissions
@property
def test_runner(self):
return self._test_runner

Просмотреть файл

@ -39,4 +39,3 @@ class TestPackage(test_jar.TestJar):
if (self._test_support_apk_path and
os.path.exists(self._test_support_apk_path)):
device.Install(self._test_support_apk_path)

Просмотреть файл

@ -64,8 +64,10 @@ class LocalDeviceInstrumentationTestRun(
return d
def individual_device_set_up(dev, host_device_tuples):
dev.Install(self._test_instance.apk_under_test)
dev.Install(self._test_instance.test_apk)
dev.Install(self._test_instance.apk_under_test,
permissions=self._test_instance.apk_under_test_permissions)
dev.Install(self._test_instance.test_apk,
permissions=self._test_instance.test_permissions)
external_storage = dev.GetExternalStoragePath()
host_device_tuples = [