Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
8451b669
Commit
8451b669
authored
Apr 19, 2016
by
Jason Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Collect trace data through the observatory HTTP interface (#3393)
parent
61605a9d
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
64 additions
and
66 deletions
+64
-66
android_device.dart
packages/flutter_tools/lib/src/android/android_device.dart
+50
-59
trace.dart
packages/flutter_tools/lib/src/commands/trace.dart
+11
-6
pubspec.yaml
packages/flutter_tools/pubspec.yaml
+3
-1
No files found.
packages/flutter_tools/lib/src/android/android_device.dart
View file @
8451b669
...
...
@@ -6,13 +6,16 @@ import 'dart:async';
import
'dart:convert'
;
import
'dart:io'
;
import
'package:json_rpc_2/json_rpc_2.dart'
as
rpc
;
import
'package:path/path.dart'
as
path
;
import
'package:web_socket_channel/io.dart'
;
import
'../android/android_sdk.dart'
;
import
'../application_package.dart'
;
import
'../base/common.dart'
;
import
'../base/os.dart'
;
import
'../base/process.dart'
;
import
'../base/utils.dart'
;
import
'../build_configuration.dart'
;
import
'../device.dart'
;
import
'../flx.dart'
as
flx
;
...
...
@@ -348,16 +351,6 @@ class AndroidDevice extends Device {
return
_portForwarder
;
}
void
startTracing
(
AndroidApk
apk
)
{
runCheckedSync
(
adbCommandForDevice
(<
String
>[
'shell'
,
'am'
,
'broadcast'
,
'-a'
,
'
${apk.id}
.TRACING_START'
]));
}
/// Return the most recent timestamp in the Android log or `null` if there is
/// no available timestamp. The format can be passed to logcat's -T option.
String
get
lastLogcatTimestamp
{
...
...
@@ -370,59 +363,57 @@ class AndroidDevice extends Device {
return
timeMatch
?.
group
(
0
);
}
Future
<
String
>
stopTracing
(
AndroidApk
apk
,
{
String
outPath
})
async
{
// Workaround for logcat -c not always working:
// http://stackoverflow.com/questions/25645012/logcat-on-android-l-not-clearing-after-unplugging-and-reconnecting
String
beforeStop
=
lastLogcatTimestamp
;
runCheckedSync
(
adbCommandForDevice
(<
String
>[
'shell'
,
'am'
,
'broadcast'
,
'-a'
,
'
${apk.id}
.TRACING_STOP'
]));
Future
<
rpc
.
Client
>
_connectToObservatory
(
int
observatoryPort
)
async
{
Uri
uri
=
new
Uri
(
scheme:
'ws'
,
host:
'127.0.0.1'
,
port:
observatoryPort
,
path:
'ws'
);
WebSocket
ws
=
await
WebSocket
.
connect
(
uri
.
toString
());
rpc
.
Client
client
=
new
rpc
.
Client
(
new
IOWebSocketChannel
(
ws
));
client
.
listen
();
return
client
;
}
RegExp
traceRegExp
=
new
RegExp
(
r'Saving trace to (\S+)'
,
multiLine:
true
);
RegExp
completeRegExp
=
new
RegExp
(
r'Trace complete'
,
multiLine:
true
);
String
tracePath
;
bool
isComplete
=
false
;
while
(!
isComplete
)
{
List
<
String
>
args
=
<
String
>[
'logcat'
,
'-d'
];
if
(
beforeStop
!=
null
)
args
.
addAll
(<
String
>[
'-T'
,
beforeStop
]);
String
logs
=
runCheckedSync
(
adbCommandForDevice
(
args
));
Match
fileMatch
=
traceRegExp
.
firstMatch
(
logs
);
if
(
fileMatch
!=
null
&&
fileMatch
[
1
]
!=
null
)
{
tracePath
=
fileMatch
[
1
];
}
isComplete
=
completeRegExp
.
hasMatch
(
logs
);
Future
<
Null
>
startTracing
(
AndroidApk
apk
,
int
observatoryPort
)
async
{
rpc
.
Client
client
;
try
{
client
=
await
_connectToObservatory
(
observatoryPort
);
}
catch
(
e
)
{
printError
(
'Error connecting to observatory:
$e
'
);
return
;
}
if
(
tracePath
!=
null
)
{
String
localPath
=
(
outPath
!=
null
)
?
outPath
:
path
.
basename
(
tracePath
);
// Run cat via ADB to print the captured trace file. (adb pull will be unable
// to access the file if it does not have root permissions)
IOSink
catOutput
=
new
File
(
localPath
).
openWrite
();
List
<
String
>
catCommand
=
adbCommandForDevice
(
<
String
>[
'shell'
,
'run-as'
,
apk
.
id
,
'cat'
,
tracePath
]
);
Process
catProcess
=
await
Process
.
start
(
catCommand
[
0
],
catCommand
.
getRange
(
1
,
catCommand
.
length
).
toList
());
catProcess
.
stdout
.
pipe
(
catOutput
);
int
exitCode
=
await
catProcess
.
exitCode
;
if
(
exitCode
!=
0
)
throw
'Error code
$exitCode
returned when running
${catCommand.join(" ")}
'
;
runSync
(
adbCommandForDevice
(
<
String
>[
'shell'
,
'run-as'
,
apk
.
id
,
'rm'
,
tracePath
]
));
return
localPath
;
await
client
.
sendRequest
(
'_setVMTimelineFlags'
,
{
'recordedStreams'
:
[
'Compiler'
,
'Dart'
,
'Embedder'
,
'GC'
]}
);
await
client
.
sendRequest
(
'_clearVMTimeline'
);
}
Future
<
String
>
stopTracing
(
AndroidApk
apk
,
int
observatoryPort
,
String
outPath
)
async
{
rpc
.
Client
client
;
try
{
client
=
await
_connectToObservatory
(
observatoryPort
);
}
catch
(
e
)
{
printError
(
'Error connecting to observatory:
$e
'
);
return
null
;
}
printError
(
'No trace file detected. '
'Did you remember to start the trace before stopping it?'
);
return
null
;
await
client
.
sendRequest
(
'_setVMTimelineFlags'
,
{
'recordedStreams'
:
'[]'
});
File
localFile
;
if
(
outPath
!=
null
)
{
localFile
=
new
File
(
outPath
);
}
else
{
localFile
=
getUniqueFile
(
Directory
.
current
,
'trace'
,
'json'
);
}
Map
<
String
,
dynamic
>
response
=
await
client
.
sendRequest
(
'_getVMTimeline'
);
List
<
dynamic
>
traceEvents
=
response
[
'traceEvents'
];
IOSink
sink
=
localFile
.
openWrite
();
Stream
<
Object
>
streamIn
=
new
Stream
<
Object
>.
fromIterable
(<
Object
>[
traceEvents
]);
Stream
<
List
<
int
>>
streamOut
=
new
JsonUtf8Encoder
().
bind
(
streamIn
);
await
sink
.
addStream
(
streamOut
);
await
sink
.
close
();
return
path
.
basename
(
localFile
.
path
);
}
@override
...
...
packages/flutter_tools/lib/src/commands/trace.dart
View file @
8451b669
...
...
@@ -6,6 +6,7 @@ import 'dart:async';
import
'../android/android_device.dart'
;
import
'../application_package.dart'
;
import
'../base/common.dart'
;
import
'../globals.dart'
;
import
'../runner/flutter_command.dart'
;
...
...
@@ -16,6 +17,9 @@ class TraceCommand extends FlutterCommand {
argParser
.
addOption
(
'out'
,
help:
'Specify the path of the saved trace file.'
);
argParser
.
addOption
(
'duration'
,
defaultsTo:
'10'
,
abbr:
'd'
,
help:
'Duration in seconds to trace.'
);
argParser
.
addOption
(
'debug-port'
,
defaultsTo:
observatoryDefaultPort
.
toString
(),
help:
'Local port where the observatory is listening.'
);
}
@override
...
...
@@ -40,26 +44,27 @@ class TraceCommand extends FlutterCommand {
Future
<
int
>
runInProject
()
async
{
ApplicationPackage
androidApp
=
applicationPackages
.
android
;
AndroidDevice
device
=
deviceForCommand
;
int
observatoryPort
=
int
.
parse
(
argResults
[
'debug-port'
]);
if
((!
argResults
[
'start'
]
&&
!
argResults
[
'stop'
])
||
(
argResults
[
'start'
]
&&
argResults
[
'stop'
]))
{
// Setting neither flags or both flags means do both commands and wait
// duration seconds in between.
device
.
startTracing
(
androidApp
);
await
device
.
startTracing
(
androidApp
,
observatoryPort
);
await
new
Future
<
Null
>.
delayed
(
new
Duration
(
seconds:
int
.
parse
(
argResults
[
'duration'
])),
()
=>
_stopTracing
(
device
,
androidApp
)
()
=>
_stopTracing
(
device
,
androidApp
,
observatoryPort
)
);
}
else
if
(
argResults
[
'stop'
])
{
await
_stopTracing
(
device
,
androidApp
);
await
_stopTracing
(
device
,
androidApp
,
observatoryPort
);
}
else
{
device
.
startTracing
(
androidApp
);
await
device
.
startTracing
(
androidApp
,
observatoryPort
);
}
return
0
;
}
Future
<
Null
>
_stopTracing
(
AndroidDevice
android
,
AndroidApk
androidApp
)
async
{
String
tracePath
=
await
android
.
stopTracing
(
androidApp
,
o
utPath:
argResults
[
'out'
]);
Future
<
Null
>
_stopTracing
(
AndroidDevice
android
,
AndroidApk
androidApp
,
int
observatoryPort
)
async
{
String
tracePath
=
await
android
.
stopTracing
(
androidApp
,
o
bservatoryPort
,
argResults
[
'out'
]);
if
(
tracePath
==
null
)
{
printError
(
'No trace file saved.'
);
}
else
{
...
...
packages/flutter_tools/pubspec.yaml
View file @
8451b669
...
...
@@ -13,14 +13,16 @@ dependencies:
crypto
:
0.9.2
file
:
^0.1.0
http
:
^0.11.3
json_rpc_2
:
^2.0.0
json_schema
:
^1.0.3
mustache4dart
:
^1.0.0
package_config
:
^0.1.3
path
:
^1.3.0
pub_semver
:
^1.0.0
stack_trace
:
^1.4.0
yaml
:
^2.1.3
web_socket_channel
:
^1.0.0
xml
:
^2.4.1
yaml
:
^2.1.3
flx
:
path
:
../flx
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment