Skip to content

Commit 96f3edc

Browse files
committed
Improve Dumpsys
- Resolve main Activity if package is provided to startActivity()
1 parent 56ebbd1 commit 96f3edc

File tree

3 files changed

+68
-23
lines changed

3 files changed

+68
-23
lines changed

src/com/dtmilano/android/adb/adbclient.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -774,9 +774,30 @@ def longPress(self, name, duration=0.5, dev='/dev/input/event0', scancode=0, rep
774774
else:
775775
raise RuntimeError("longpress: not supported for API < 19 (version=%d)" % version)
776776

777-
def startActivity(self, component=None, flags=None, uri=None):
777+
def resolveActivity(self, package):
778+
version = self.getSdkVersion()
779+
if version < 24:
780+
raise RuntimeError(f'resolve-activity: not supported for API < 24 (version={version})')
781+
cmd = f'cmd package resolve-activity --brief {package}'
782+
lines = self.shell(cmd).splitlines()
783+
if len(lines) != 2:
784+
raise RuntimeError(f'resolve-activity: cannot resolve activity for package {package}')
785+
return lines[1]
786+
787+
def startActivity(self, component=None, flags=None, uri=None, package=None):
788+
"""
789+
Starts an Activity.
790+
If package is specified instead of component the corresponding MAIN activity for the package
791+
will be resolved and used.
792+
"""
778793
self.__checkTransport()
779794
cmd = 'am start'
795+
if package and not component:
796+
version = self.getSdkVersion()
797+
if version >= 24:
798+
component = self.resolveActivity(package)
799+
else:
800+
component = self.dumpsys(Dumpsys.PACKAGE, package).package['main-activity']
780801
if component:
781802
cmd += ' -n %s' % component
782803
if flags:
@@ -1367,8 +1388,8 @@ def substituteDeviceTemplate(self, template):
13671388
}
13681389
return string.Template(template).substitute(_map)
13691390

1370-
def dumpsys(self, subcommand, args):
1371-
return Dumpsys(self, subcommand, args)
1391+
def dumpsys(self, subcommand, *args):
1392+
return Dumpsys(self, subcommand, *args)
13721393

13731394

13741395
if __name__ == '__main__':

src/com/dtmilano/android/adb/dumpsys.py

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
'''
2-
Copyright (C) 2012-2018 Diego Torres Milano
1+
"""
2+
Copyright (C) 2012-2021 Diego Torres Milano
33
Created on Dec 1, 2012
44
55
Licensed under the Apache License, Version 2.0 (the "License");
66
you may not use this file except in compliance with the License.
77
You may obtain a copy of the License at
88
9-
http://www.apache.org/licenses/LICENSE-2.0
9+
https://www.apache.org/licenses/LICENSE-2.0
1010
1111
Unless required by applicable law or agreed to in writing, software
1212
distributed under the License is distributed on an "AS IS" BASIS,
@@ -15,7 +15,7 @@
1515
limitations under the License.
1616
1717
@author: Diego Torres Milano
18-
'''
18+
"""
1919

2020
from __future__ import print_function
2121

@@ -34,7 +34,8 @@ class Dumpsys:
3434
MEMINFO = 'meminfo'
3535
RESET = 'reset'
3636

37-
ACTIVITIES = 'activities'
37+
ACTIVITY = 'activity'
38+
PACKAGE = 'package'
3839
TOTAL = 'total'
3940
VIEW_ROOT_IMPL = 'viewRootImpl'
4041
VIEWS = 'views'
@@ -44,11 +45,13 @@ class Dumpsys:
4445
FRAME_COMPLETED = 13
4546

4647
def __init__(self, adbclient, subcommand, *args):
48+
self.out = None
4749
self.nativeHeap = -1
4850
self.dalvikHeap = -1
4951
self.total = 0
5052
self.views = -1
51-
self.activities = -1
53+
self.activity = -1
54+
self.package = dict()
5255
self.appContexts = -1
5356
self.viewRootImpl = -1
5457
self.gfxProfileData = []
@@ -85,37 +88,57 @@ def parse(self, out, subcommand, *args):
8588
self.parseGfxinfoFramestats(out)
8689
else:
8790
self.parseGfxinfo(out)
88-
elif '-l':
91+
elif subcommand == Dumpsys.ACTIVITY:
92+
self.activity = out
93+
elif subcommand == Dumpsys.PACKAGE:
94+
if len(args) > 0 and Dumpsys.isPackageName(args[0]):
95+
self.parsePackage(out)
96+
else:
97+
self.package['out'] = out
98+
elif subcommand == '-l':
8999
# list dumpsys subcommands
90-
return out
100+
self.out = out
91101
else:
92-
pass
102+
self.out = out
103+
104+
@staticmethod
105+
def isPackageName(name):
106+
return re.search(r'\S+\.\S+.*', name)
107+
108+
def parsePackage(self, out):
109+
lines = out.splitlines()
110+
for i in range(len(lines)):
111+
if re.match(r'\s*Non-Data Actions:', lines[i]):
112+
if re.match(r'\s*android.intent.action.MAIN:', lines[i + 1]):
113+
a = lines[i + 2].split()
114+
if len(a) >= 4:
115+
self.package['main-activity'] = a[1]
93116

94117
def parseMeminfo(self, out):
95-
m = re.search('Native Heap[ \t]*(\d+)', out, re.MULTILINE)
118+
m = re.search(r'Native Heap[ \t]*(\d+)', out, re.MULTILINE)
96119
if m:
97120
self.nativeHeap = int(m.group(1))
98-
m = re.search('Dalvik Heap[ \t]*(\d+)', out, re.MULTILINE)
121+
m = re.search(r'Dalvik Heap[ \t]*(\d+)', out, re.MULTILINE)
99122
if m:
100123
self.dalvikHeap = int(m.group(1))
101-
m = re.search('Views:[ \t]*(\d+)', out, re.MULTILINE)
124+
m = re.search(r'Views:[ \t]*(\d+)', out, re.MULTILINE)
102125
if m:
103126
self.views = int(m.group(1))
104-
m = re.search('Activities:[ \t]*(\d+)', out, re.MULTILINE)
127+
m = re.search(r'Activities:[ \t]*(\d+)', out, re.MULTILINE)
105128
if m:
106-
self.activities = int(m.group(1))
107-
m = re.search('AppContexts:[ \t]*(\d+)', out, re.MULTILINE)
129+
self.activity = int(m.group(1))
130+
m = re.search(r'AppContexts:[ \t]*(\d+)', out, re.MULTILINE)
108131
if m:
109132
self.appContexts = int(m.group(1))
110-
m = re.search('ViewRootImpl:[ \t]*(\d+)', out, re.MULTILINE)
133+
m = re.search(r'ViewRootImpl:[ \t]*(\d+)', out, re.MULTILINE)
111134
if m:
112135
self.viewRootImpl = int(m.group(1))
113136

114-
m = re.search('TOTAL[ \t]*(\d+)', out, re.MULTILINE)
137+
m = re.search(r'TOTAL[ \t]*(\d+)', out, re.MULTILINE)
115138
if m:
116139
self.total = int(m.group(1))
117140
else:
118-
raise RuntimeError('Cannot find TOTAL in "' + out + '"')
141+
raise RuntimeError(f'Cannot find TOTAL in "{out}"')
119142

120143
def parseGfxinfo(self, out):
121144
pass
@@ -134,8 +157,8 @@ def parseGfxinfoFramestats(self, out):
134157
continue
135158
pda = s.split(',')
136159
if pda[Dumpsys.FLAGS] == 'Flags':
137-
if pda[Dumpsys.INTENDED_VSYNC] != 'IntendedVsync' and pda[
138-
Dumpsys.FRAME_COMPLETED] != 'FrameCompleted':
160+
if pda[Dumpsys.INTENDED_VSYNC] != 'IntendedVsync' and \
161+
pda[Dumpsys.FRAME_COMPLETED] != 'FrameCompleted':
139162
raise RuntimeError('Unsupported gfxinfo version')
140163
continue
141164
if pda[Dumpsys.FLAGS] == '0':

src/com/dtmilano/android/plot.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ def plot(self, _type=Dumpsys.MEMINFO, filename=None):
161161
raise RuntimeError("No values to plot")
162162
elif _type == Dumpsys.FRAMESTATS:
163163
if DEBUG:
164+
print(" plot: numpy version {} (should be > 1.8)".format(np.__version__), file=sys.stderr)
164165
print(" plot: histogram {}".format(self.aava[Dumpsys.FRAMESTATS]), file=sys.stderr)
165166
n, bins, patches = plt.hist(self.aava[Dumpsys.FRAMESTATS])
166167
ymax = np.amax(n)

0 commit comments

Comments
 (0)