OLD | NEW |
1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Module containing utilities for apk packages.""" | 5 """Module containing utilities for apk packages.""" |
6 | 6 |
7 import os.path | |
8 import re | 7 import re |
9 | 8 |
10 from devil.android.sdk import aapt | 9 from devil.android.sdk import aapt |
11 from pylib import constants | |
12 | 10 |
13 | 11 |
14 _AAPT_PATH = os.path.join(constants.ANDROID_SDK_TOOLS, 'aapt') | |
15 _MANIFEST_ATTRIBUTE_RE = re.compile( | 12 _MANIFEST_ATTRIBUTE_RE = re.compile( |
16 r'\s*A: ([^\(\)= ]*)\([^\(\)= ]*\)=(?:"(.*)" \(Raw: .*\)|\(type.*?\)(.*))$') | 13 r'\s*A: ([^\(\)= ]*)(?:\([^\(\)= ]*\))?=' |
| 14 r'(?:"(.*)" \(Raw: .*\)|\(type.*?\)(.*))$') |
17 _MANIFEST_ELEMENT_RE = re.compile(r'\s*(?:E|N): (\S*) .*$') | 15 _MANIFEST_ELEMENT_RE = re.compile(r'\s*(?:E|N): (\S*) .*$') |
18 _PACKAGE_NAME_RE = re.compile(r'package: .*name=\'(\S*)\'') | |
19 _SPLIT_NAME_RE = re.compile(r'package: .*split=\'(\S*)\'') | |
20 | 16 |
21 | 17 |
22 def GetPackageName(apk_path): | 18 def GetPackageName(apk_path): |
23 """Returns the package name of the apk.""" | 19 """Returns the package name of the apk.""" |
24 return ApkHelper(apk_path).GetPackageName() | 20 return ApkHelper(apk_path).GetPackageName() |
25 | 21 |
26 | 22 |
27 # TODO(jbudorick): Deprecate and remove this function once callers have been | 23 # TODO(jbudorick): Deprecate and remove this function once callers have been |
28 # converted to ApkHelper.GetInstrumentationName | 24 # converted to ApkHelper.GetInstrumentationName |
29 def GetInstrumentationName(apk_path): | 25 def GetInstrumentationName(apk_path): |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 node[m.group(1)].append(m.group(2) or m.group(3)) | 59 node[m.group(1)].append(m.group(2) or m.group(3)) |
64 continue | 60 continue |
65 | 61 |
66 return parsed_manifest | 62 return parsed_manifest |
67 | 63 |
68 | 64 |
69 class ApkHelper(object): | 65 class ApkHelper(object): |
70 def __init__(self, apk_path): | 66 def __init__(self, apk_path): |
71 self._apk_path = apk_path | 67 self._apk_path = apk_path |
72 self._manifest = None | 68 self._manifest = None |
73 self._package_name = None | |
74 self._split_name = None | |
75 self._has_isolated_processes = None | |
76 | 69 |
77 def GetActivityName(self): | 70 def GetActivityName(self): |
78 """Returns the name of the Activity in the apk.""" | 71 """Returns the name of the Activity in the apk.""" |
79 manifest_info = self._GetManifest() | 72 manifest_info = self._GetManifest() |
80 try: | 73 try: |
81 activity = ( | 74 activity = ( |
82 manifest_info['manifest']['application']['activity'] | 75 manifest_info['manifest']['application']['activity'] |
83 ['android:name'][0]) | 76 ['android:name'][0]) |
84 except KeyError: | 77 except KeyError: |
85 return None | 78 return None |
86 if '.' not in activity: | 79 if '.' not in activity: |
87 activity = '%s.%s' % (self.GetPackageName(), activity) | 80 activity = '%s.%s' % (self.GetPackageName(), activity) |
88 elif activity.startswith('.'): | 81 elif activity.startswith('.'): |
89 activity = '%s%s' % (self.GetPackageName(), activity) | 82 activity = '%s%s' % (self.GetPackageName(), activity) |
90 return activity | 83 return activity |
91 | 84 |
92 def GetInstrumentationName( | 85 def GetInstrumentationName( |
93 self, default='android.test.InstrumentationTestRunner'): | 86 self, default='android.test.InstrumentationTestRunner'): |
94 """Returns the name of the Instrumentation in the apk.""" | 87 """Returns the name of the Instrumentation in the apk.""" |
95 manifest_info = self._GetManifest() | 88 manifest_info = self._GetManifest() |
96 try: | 89 try: |
97 return manifest_info['manifest']['instrumentation']['android:name'][0] | 90 return manifest_info['manifest']['instrumentation']['android:name'][0] |
98 except KeyError: | 91 except KeyError: |
99 return default | 92 return default |
100 | 93 |
101 def GetPackageName(self): | 94 def GetPackageName(self): |
102 """Returns the package name of the apk.""" | 95 """Returns the package name of the apk.""" |
103 if self._package_name: | 96 manifest_info = self._GetManifest() |
104 return self._package_name | 97 try: |
105 | 98 return manifest_info['manifest']['package'][0] |
106 aapt_output = aapt.Dump('badging', self._apk_path) | 99 except KeyError: |
107 for line in aapt_output: | 100 raise Exception('Failed to determine package name of %s' % self._apk_path) |
108 m = _PACKAGE_NAME_RE.match(line) | |
109 if m: | |
110 self._package_name = m.group(1) | |
111 return self._package_name | |
112 raise Exception('Failed to determine package name of %s' % self._apk_path) | |
113 | 101 |
114 def GetPermissions(self): | 102 def GetPermissions(self): |
115 manifest_info = self._GetManifest() | 103 manifest_info = self._GetManifest() |
116 try: | 104 try: |
117 return manifest_info['manifest']['uses-permission']['android:name'] | 105 return manifest_info['manifest']['uses-permission']['android:name'] |
118 except KeyError: | 106 except KeyError: |
119 return [] | 107 return [] |
120 | 108 |
121 def GetSplitName(self): | 109 def GetSplitName(self): |
122 """Returns the name of the split of the apk.""" | 110 """Returns the name of the split of the apk.""" |
123 if self._split_name: | 111 manifest_info = self._GetManifest() |
124 return self._split_name | 112 try: |
125 | 113 return manifest_info['manifest']['split'][0] |
126 aapt_output = aapt.Dump('badging', self._apk_path) | 114 except KeyError: |
127 for line in aapt_output: | 115 return None |
128 m = _SPLIT_NAME_RE.match(line) | |
129 if m: | |
130 self._split_name = m.group(1) | |
131 return self._split_name | |
132 return None | |
133 | 116 |
134 def HasIsolatedProcesses(self): | 117 def HasIsolatedProcesses(self): |
135 """Returns whether any services exist that use isolatedProcess=true.""" | 118 """Returns whether any services exist that use isolatedProcess=true.""" |
136 if self._has_isolated_processes is None: | 119 manifest_info = self._GetManifest() |
137 manifest_info = self._GetManifest() | 120 try: |
138 try: | 121 services = manifest_info['manifest']['application']['service'] |
139 services = manifest_info['manifest']['application']['service'] | 122 return any(int(v, 0) for v in services['android:isolatedProcess']) |
140 self._has_isolated_processes = ( | 123 except KeyError: |
141 any(int(v, 0) for v in services['android:isolatedProcess'])) | 124 return False |
142 except KeyError: | |
143 self._has_isolated_processes = False | |
144 return self._has_isolated_processes | |
145 | 125 |
146 def _GetManifest(self): | 126 def _GetManifest(self): |
147 if not self._manifest: | 127 if not self._manifest: |
148 self._manifest = _ParseManifestFromApk(self._apk_path) | 128 self._manifest = _ParseManifestFromApk(self._apk_path) |
149 return self._manifest | 129 return self._manifest |
150 | 130 |
OLD | NEW |