Exemple #1
0
        /// <summary>
        /// Reads the next <see cref="LogEntry"/> from the stream.
        /// </summary>
        /// <returns>
        /// A new <see cref="LogEntry"/> object.
        /// </returns>
        public async Task <LogEntry> ReadEntry(CancellationToken cancellationToken)
        {
            LogEntry value = new LogEntry();

            // Read the log data in binary format. This format is defined at
            // https://android.googlesource.com/platform/system/core/+/master/include/log/logger.h
            var payloadLengthValue = await this.ReadUInt16Async(cancellationToken).ConfigureAwait(false);

            var headerSizeValue = payloadLengthValue == null ? null : await this.ReadUInt16Async(cancellationToken).ConfigureAwait(false);

            var pidValue = headerSizeValue == null ? null : await this.ReadInt32Async(cancellationToken).ConfigureAwait(false);

            var tidValue = pidValue == null ? null : await this.ReadInt32Async(cancellationToken).ConfigureAwait(false);

            var secValue = tidValue == null ? null : await this.ReadInt32Async(cancellationToken).ConfigureAwait(false);

            var nsecValue = secValue == null ? null : await this.ReadInt32Async(cancellationToken).ConfigureAwait(false);

            if (nsecValue == null)
            {
                return(null);
            }

            var payloadLength = payloadLengthValue.Value;
            var headerSize    = headerSizeValue.Value;
            var pid           = pidValue.Value;
            var tid           = tidValue.Value;
            var sec           = secValue.Value;
            var nsec          = nsecValue.Value;

            // If the headerSize is not 0, we have either a logger_entry_v3 or logger_entry_v2 object.
            // For both objects, the size should be 0x18
            uint id = 0;

            if (headerSize != 0)
            {
                if (headerSize == 0x18)
                {
                    var idValue = await this.ReadUInt32Async(cancellationToken).ConfigureAwait(false);

                    if (idValue == null)
                    {
                        return(null);
                    }

                    id = idValue.Value;
                }
                else
                {
                    throw new Exception();
                }
            }

            byte[] data = await this.ReadBytesSafeAsync(payloadLength, cancellationToken).ConfigureAwait(false);

            if (data == null)
            {
                return(null);
            }

            DateTime timestamp = DateTimeHelper.Epoch.AddSeconds(sec);

            timestamp = timestamp.AddMilliseconds(nsec / 1000000d);

            switch ((LogId)id)
            {
            case LogId.Crash:
            case LogId.Kernel:
            case LogId.Main:
            case LogId.Radio:
            case LogId.System:
            {
                // format: <priority:1><tag:N>\0<message:N>\0
                var priority = data[0];

                // Find the first \0 byte in the array. This is the seperator
                // between the tag and the actual message
                int tagEnd = 1;

                while (data[tagEnd] != '\0' && tagEnd < data.Length)
                {
                    tagEnd++;
                }

                // Message should be null termintated, so remove the last entry, too (-2 instead of -1)
                string tag     = Encoding.ASCII.GetString(data, 1, tagEnd - 1);
                string message = Encoding.ASCII.GetString(data, tagEnd + 1, data.Length - tagEnd - 2);

                return(new AndroidLogEntry()
                    {
                        Data = data,
                        ProcessId = pid,
                        ThreadId = tid,
                        TimeStamp = timestamp,
                        Id = id,
                        Priority = (Priority)priority,
                        Message = message,
                        Tag = tag
                    });
            }

            case LogId.Events:
            {
                // https://android.googlesource.com/platform/system/core.git/+/master/liblog/logprint.c#547
                var entry = new EventLogEntry()
                {
                    Data      = data,
                    ProcessId = pid,
                    ThreadId  = tid,
                    TimeStamp = timestamp,
                    Id        = id
                };

                // Use a stream on the data buffer. This will make sure that,
                // if anything goes wrong parsing the data, we never go past
                // the message boundary itself.
                using (MemoryStream dataStream = new MemoryStream(data))
                    using (BinaryReader reader = new BinaryReader(dataStream))
                    {
                        var priority = reader.ReadInt32();

                        while (dataStream.Position < dataStream.Length)
                        {
                            this.ReadLogEntry(reader, entry.Values);
                        }
                    }

                return(entry);
            }

            default:
                return(new LogEntry()
                {
                    Data = data,
                    ProcessId = pid,
                    ThreadId = tid,
                    TimeStamp = timestamp,
                    Id = id
                });
            }
        }
Exemple #2
0
        /// <summary>
        /// Reads the next <see cref="LogEntry"/> from the stream.
        /// </summary>
        /// <returns>
        /// A new <see cref="LogEntry"/> object.
        /// </returns>
        public async Task <LogEntry> ReadEntry(CancellationToken cancellationToken)
        {
            LogEntry value = new LogEntry();

            // Read the log data in binary format. This format is defined at
            // https://android.googlesource.com/platform/system/core/+/master/include/log/logger.h
            // https://android.googlesource.com/platform/system/core/+/67d7eaf/include/log/logger.h
            var payloadLengthValue = await this.ReadUInt16Async(cancellationToken).ConfigureAwait(false);

            var headerSizeValue = payloadLengthValue == null ? null : await this.ReadUInt16Async(cancellationToken).ConfigureAwait(false);

            var pidValue = headerSizeValue == null ? null : await this.ReadInt32Async(cancellationToken).ConfigureAwait(false);

            var tidValue = pidValue == null ? null : await this.ReadInt32Async(cancellationToken).ConfigureAwait(false);

            var secValue = tidValue == null ? null : await this.ReadInt32Async(cancellationToken).ConfigureAwait(false);

            var nsecValue = secValue == null ? null : await this.ReadInt32Async(cancellationToken).ConfigureAwait(false);

            if (nsecValue == null)
            {
                return(null);
            }

            var payloadLength = payloadLengthValue.Value;
            var headerSize    = headerSizeValue.Value;
            var pid           = pidValue.Value;
            var tid           = tidValue.Value;
            var sec           = secValue.Value;
            var nsec          = nsecValue.Value;

            // If the headerSize is not 0, we have on of the logger_entry_v* objects.
            // In all cases, it appears that they always start with a two uint16's giving the
            // header size and payload length.
            // For both objects, the size should be 0x18
            uint id  = 0;
            uint uid = 0;

            if (headerSize != 0)
            {
                if (headerSize >= 0x18)
                {
                    var idValue = await this.ReadUInt32Async(cancellationToken).ConfigureAwait(false);

                    if (idValue == null)
                    {
                        return(null);
                    }

                    id = idValue.Value;
                }

                if (headerSize >= 0x1c)
                {
                    var uidValue = await this.ReadUInt32Async(cancellationToken).ConfigureAwait(false);

                    if (uidValue == null)
                    {
                        return(null);
                    }

                    uid = uidValue.Value;
                }

                if (headerSize >= 0x20)
                {
                    // Not sure what this is.
                    await this.ReadUInt32Async(cancellationToken).ConfigureAwait(false);
                }

                if (headerSize > 0x20)
                {
                    throw new AdbException($"An error occurred while reading data from the ADB stream. Although the header size was expected to be 0x18, a header size of 0x{headerSize:X} was sent by the device");
                }
            }

            byte[] data = await this.ReadBytesSafeAsync(payloadLength, cancellationToken).ConfigureAwait(false);

            if (data == null)
            {
                return(null);
            }

            var timestamp = DateTimeOffset.FromUnixTimeSeconds(sec);

            switch ((LogId)id)
            {
            case LogId.Crash:
            case LogId.Kernel:
            case LogId.Main:
            case LogId.Radio:
            case LogId.System:
            {
                // format: <priority:1><tag:N>\0<message:N>\0
                var priority = data[0];

                // Find the first \0 byte in the array. This is the seperator
                // between the tag and the actual message
                int tagEnd = 1;

                while (data[tagEnd] != '\0' && tagEnd < data.Length)
                {
                    tagEnd++;
                }

                // Message should be null termintated, so remove the last entry, too (-2 instead of -1)
                string tag     = Encoding.ASCII.GetString(data, 1, tagEnd - 1);
                string message = Encoding.ASCII.GetString(data, tagEnd + 1, data.Length - tagEnd - 2);

                return(new AndroidLogEntry()
                    {
                        Data = data,
                        ProcessId = pid,
                        ThreadId = tid,
                        TimeStamp = timestamp,
                        Id = id,
                        Priority = (Priority)priority,
                        Message = message,
                        Tag = tag
                    });
            }

            case LogId.Events:
            {
                // https://android.googlesource.com/platform/system/core.git/+/master/liblog/logprint.c#547
                var entry = new EventLogEntry()
                {
                    Data      = data,
                    ProcessId = pid,
                    ThreadId  = tid,
                    TimeStamp = timestamp,
                    Id        = id
                };

                // Use a stream on the data buffer. This will make sure that,
                // if anything goes wrong parsing the data, we never go past
                // the message boundary itself.
                using (MemoryStream dataStream = new MemoryStream(data))
                    using (BinaryReader reader = new BinaryReader(dataStream))
                    {
                        var priority = reader.ReadInt32();

                        while (dataStream.Position < dataStream.Length)
                        {
                            this.ReadLogEntry(reader, entry.Values);
                        }
                    }

                return(entry);
            }

            default:
                return(new LogEntry()
                {
                    Data = data,
                    ProcessId = pid,
                    ThreadId = tid,
                    TimeStamp = timestamp,
                    Id = id
                });
            }
        }
Exemple #3
0
        /// <summary>
        /// Reads the next <see cref="LogEntry"/> from the stream.
        /// </summary>
        /// <returns>
        /// A new <see cref="LogEntry"/> object.
        /// </returns>
        public LogEntry ReadEntry()
        {
            LogEntry value = new LogEntry();

            // Read the log data in binary format. This format is defined at
            // https://android.googlesource.com/platform/system/core/+/master/include/log/logger.h
            var payloadLength = this.ReadUInt16();
            var headerSize = this.ReadUInt16();
            var pid = this.ReadInt32();
            var tid = this.ReadInt32();
            var sec = this.ReadInt32();
            var nsec = this.ReadInt32();

            // If the headerSize is not 0, we have either a logger_entry_v3 or logger_entry_v2 object.
            // For both objects, the size should be 0x18
            uint id = 0;
            if (headerSize != 0)
            {
                if (headerSize == 0x18)
                {
                    id = this.ReadUInt32();
                }
                else
                {
                    throw new Exception();
                }
            }

            byte[] data = this.ReadBytes(payloadLength);

            DateTime timestamp = DateTimeHelper.Epoch.AddSeconds(sec);
            timestamp = timestamp.AddMilliseconds(nsec / 1000000d);

            switch ((LogId)id)
            {
                case LogId.Crash:
                case LogId.Kernel:
                case LogId.Main:
                case LogId.Radio:
                case LogId.System:
                    {
                        // format: <priority:1><tag:N>\0<message:N>\0
                        var priority = data[0];

                        // Find the first \0 byte in the array. This is the seperator
                        // between the tag and the actual message
                        int tagEnd = 1;

                        while (data[tagEnd] != '\0' && tagEnd < data.Length)
                        {
                            tagEnd++;
                        }

                        // Message should be null termintated, so remove the last entry, too (-2 instead of -1)
                        string tag = Encoding.ASCII.GetString(data, 1, tagEnd - 1);
                        string message = Encoding.ASCII.GetString(data, tagEnd + 1, data.Length - tagEnd - 2);

                        return new AndroidLogEntry()
                        {
                            Data = data,
                            ProcessId = pid,
                            ThreadId = tid,
                            TimeStamp = timestamp,
                            Id = id,
                            Priority = priority,
                            Message = message,
                            Tag = tag
                        };
                    }

                case LogId.Events:
                    {
                        // https://android.googlesource.com/platform/system/core.git/+/master/liblog/logprint.c#547
                        var entry = new EventLogEntry()
                        {
                            Data = data,
                            ProcessId = pid,
                            ThreadId = tid,
                            TimeStamp = timestamp,
                            Id = id
                        };

                        // Use a stream on the data buffer. This will make sure that,
                        // if anything goes wrong parsing the data, we never go past
                        // the message boundary itself.
                        using (MemoryStream stream = new MemoryStream(data))
                        using (BinaryReader reader = new BinaryReader(stream))
                        {
                            var priority = reader.ReadInt32();

                            while (stream.Position < stream.Length)
                            {
                                this.ReadLogEntry(reader, entry.Values);
                            }
                        }

                        return entry;
                    }

                default:
                    return new LogEntry()
                    {
                        Data = data,
                        ProcessId = pid,
                        ThreadId = tid,
                        TimeStamp = timestamp,
                        Id = id
                    };
            }
        }