@@ -528,15 +528,16 @@ class AndroidDevice extends Device {
528
528
return _portForwarder;
529
529
}
530
530
531
+ static RegExp _timeRegExp = new RegExp (r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}' , multiLine: true );
532
+
531
533
/// Return the most recent timestamp in the Android log or `null` if there is
532
534
/// no available timestamp. The format can be passed to logcat's -T option.
533
535
String get lastLogcatTimestamp {
534
536
String output = runCheckedSync (adbCommandForDevice (< String > [
535
537
'logcat' , '-v' , 'time' , '-t' , '1'
536
538
]));
537
539
538
- RegExp timeRegExp = new RegExp (r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}' , multiLine: true );
539
- Match timeMatch = timeRegExp.firstMatch (output);
540
+ Match timeMatch = _timeRegExp.firstMatch (output);
540
541
return timeMatch? .group (0 );
541
542
}
542
543
@@ -726,24 +727,24 @@ class _AdbLogReader extends DeviceLogReader {
726
727
@override
727
728
String get name => device.name;
728
729
730
+ DateTime _timeOrigin;
731
+
732
+ DateTime _adbTimestampToDateTime (String adbTimestamp) {
733
+ // The adb timestamp format is: mm-dd hours:minutes:seconds.milliseconds
734
+ // Dart's DateTime parse function accepts this format so long as we provide
735
+ // the year, resulting in:
736
+ // yyyy-mm-dd hours:minutes:seconds.milliseconds.
737
+ return DateTime .parse ('${new DateTime .now ().year }-$adbTimestamp ' );
738
+ }
739
+
729
740
void _start () {
730
741
// Start the adb logcat process.
731
- List <String > args = < String > ['logcat' , '-v' , 'tag ' ];
742
+ List <String > args = < String > ['logcat' , '-v' , 'time ' ];
732
743
String lastTimestamp = device.lastLogcatTimestamp;
733
- if (lastTimestamp != null ) {
734
- bool supportsLastTimestamp = false ;
735
-
736
- // Check to see if this copy of adb supports -T.
737
- try {
738
- // "logcat: invalid option -- T", "Unrecognized Option"
739
- // logcat -g will finish immediately; it will print an error to stdout if -T isn't supported.
740
- String result = runSync (device.adbCommandForDevice (< String > ['logcat' , '-g' , '-T' , lastTimestamp]));
741
- supportsLastTimestamp = ! result.contains ('logcat: invalid option' ) && ! result.contains ('Unrecognized Option' );
742
- } catch (_) { }
743
-
744
- if (supportsLastTimestamp)
745
- args.addAll (< String > ['-T' , lastTimestamp]);
746
- }
744
+ if (lastTimestamp != null )
745
+ _timeOrigin = _adbTimestampToDateTime (lastTimestamp);
746
+ else
747
+ _timeOrigin = null ;
747
748
runCommand (device.adbCommandForDevice (args)).then ((Process process) {
748
749
_process = process;
749
750
_process.stdout.transform (UTF8 .decoder).transform (const LineSplitter ()).listen (_onLine);
@@ -771,7 +772,28 @@ class _AdbLogReader extends DeviceLogReader {
771
772
// we default to true in case none of the log lines match
772
773
bool _acceptedLastLine = true ;
773
774
775
+ // The format of the line is controlled by the '-v' parameter passed to
776
+ // adb logcat. We are currently passing 'time', which has the format:
777
+ // mm-dd hh:mm:ss.milliseconds Priority/Tag( PID): ....
774
778
void _onLine (String line) {
779
+ final Match timeMatch = AndroidDevice ._timeRegExp.firstMatch (line);
780
+ if (timeMatch == null ) {
781
+ return ;
782
+ }
783
+ if (_timeOrigin != null ) {
784
+ final String timestamp = timeMatch.group (0 );
785
+ DateTime time = _adbTimestampToDateTime (timestamp);
786
+ if (time.isBefore (_timeOrigin)) {
787
+ // Ignore log messages before the origin.
788
+ printTrace ('skipped old log line: $line ' );
789
+ return ;
790
+ }
791
+ }
792
+ if (line.length == timeMatch.end) {
793
+ return ;
794
+ }
795
+ // Chop off the time.
796
+ line = line.substring (timeMatch.end + 1 );
775
797
if (_logFormat.hasMatch (line)) {
776
798
// Filter on approved names and levels.
777
799
for (RegExp regex in _whitelistedTags) {
0 commit comments