11754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato/*
21754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Copyright (C) 2016 The Android Open Source Project
31754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *
41754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
51754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * you may not use this file except in compliance with the License.
61754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * You may obtain a copy of the License at
71754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *
81754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
91754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *
101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Unless required by applicable law or agreed to in writing, software
111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * See the License for the specific language governing permissions and
141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * limitations under the License.
151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato */
161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include "generic_message.h"
181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include "printer.h"
191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
207669012623a18855913c84ec0690066fbfd823eaJoe Onorato#include <frameworks/base/core/proto/android/os/incident.pb.h>
211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <google/protobuf/wire_format.h>
221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <google/protobuf/io/coded_stream.h>
231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <google/protobuf/io/zero_copy_stream_impl.h>
241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <sys/types.h>
261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <sys/stat.h>
271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <sys/wait.h>
281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <errno.h>
291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <fcntl.h>
301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <stdio.h>
311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <string.h>
321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <unistd.h>
331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratousing namespace android::os;
351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratousing namespace google::protobuf;
361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratousing namespace google::protobuf::io;
371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratousing namespace google::protobuf::internal;
381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic bool read_message(CodedInputStream* in, Descriptor const* descriptor,
401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        GenericMessage* message);
411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic void print_message(Out* out, Descriptor const* descriptor, GenericMessage const* message);
421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato// ================================================================================
441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic bool
451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoread_length_delimited(CodedInputStream* in, uint32 fieldId, Descriptor const* descriptor,
461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        GenericMessage* message)
471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    uint32 size;
491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (!in->ReadVarint32(&size)) {
501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        return false;
511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    FieldDescriptor const* field = descriptor->FindFieldByNumber(fieldId);
541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (field != NULL) {
551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        int type = field->type();
561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (type == FieldDescriptor::TYPE_MESSAGE) {
571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            GenericMessage* child = message->addMessage(fieldId);
581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            CodedInputStream::Limit limit = in->PushLimit(size);
601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            bool rv = read_message(in, field->message_type(), child);
611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            in->PopLimit(limit);
621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return rv;
631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else if (type == FieldDescriptor::TYPE_STRING) {
641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // TODO: do a version of readstring that just pumps the data
651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // rather than allocating a string which we don't care about.
661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            string str;
671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (in->ReadString(&str, size)) {
681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                message->addString(fieldId, str);
691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return true;
701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            } else {
711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return false;
721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else if (type == FieldDescriptor::TYPE_BYTES) {
741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // TODO: Save bytes field.
751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return in->Skip(size);
761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    return in->Skip(size);
791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato// ================================================================================
821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic bool
831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoread_message(CodedInputStream* in, Descriptor const* descriptor, GenericMessage* message)
841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    uint32 value32;
861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    uint64 value64;
871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    while (true) {
891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        uint32 tag = in->ReadTag();
901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (tag == 0) {
911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return true;
921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        int fieldId = WireFormatLite::GetTagFieldNumber(tag);
941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        switch (WireFormatLite::GetTagWireType(tag)) {
951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case WireFormatLite::WIRETYPE_VARINT:
961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if (in->ReadVarint64(&value64)) {
971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    message->addInt64(fieldId, value64);
981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                } else {
1001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    return false;
1011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
1021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case WireFormatLite::WIRETYPE_FIXED64:
1031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if (in->ReadLittleEndian64(&value64)) {
1041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    message->addInt64(fieldId, value64);
1051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                } else {
1071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    return false;
1081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
1091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case WireFormatLite::WIRETYPE_LENGTH_DELIMITED:
1101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if (!read_length_delimited(in, fieldId, descriptor, message)) {
1111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    return false;
1121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
1131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                break;
1141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case WireFormatLite::WIRETYPE_FIXED32:
1151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if (in->ReadLittleEndian32(&value32)) {
1161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    message->addInt32(fieldId, value32);
1171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                } else {
1191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    return false;
1201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
1211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            default:
1221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                fprintf(stderr, "bad tag: 0x%x (%d) at index %d\n", tag, tag,
1231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        in->CurrentPosition());
1241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return false;
1251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
1261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
1271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
1281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato// ================================================================================
1301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic void
1311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoprint_value(Out* out, FieldDescriptor const* field, GenericMessage::Node const& node)
1321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
1331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    uint32_t val32;
1341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    FieldDescriptor::Type type = field->type();
1351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    switch (node.type) {
1371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        case GenericMessage::TYPE_VALUE32:
1381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            switch (type) {
1391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_FIXED32:
1401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    out->printf("%u", node.value32);
1411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_SFIXED32:
1431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    out->printf("%d", node.value32);
1441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_FLOAT:
1461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    out->printf("%f", *(float*)&node.value32);
1471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                default:
1491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    out->printf("(unexpected value %d (0x%x)", node.value32, node.value32);
1501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
1521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            break;
1531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        case GenericMessage::TYPE_VALUE64:
1541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            switch (type) {
1551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_FIXED64:
1561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_SFIXED64:
1571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_DOUBLE:
1581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    out->printf("%f", *(double*)&node.value64);
1591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_SINT32:
1611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_INT32:
1621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    val32 = (uint32_t)node.value32;
1631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    out->printf("%d", val32);
1641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_INT64:
1661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_UINT32:
1671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    val32 = (uint32_t)node.value32;
1681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    out->printf("%u", val32);
1691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_UINT64:
1711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_SINT64:
1721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_BOOL:
1731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    if (node.value64) {
1741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        out->printf("true");
1751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    } else {
1761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        out->printf("false");
1771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    }
1781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                case FieldDescriptor::TYPE_ENUM:
1801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                default:
1811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    out->printf("(unexpected value %ld (0x%x))", node.value64, node.value64);
1821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
1831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
1841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            break;
1851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        case GenericMessage::TYPE_MESSAGE:
1861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            print_message(out, field->message_type(), node.message);
1871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            break;
1881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        case GenericMessage::TYPE_STRING:
1891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // TODO: custom format for multi-line strings.
1901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            out->printf("%s", node.str->c_str());
1911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            break;
1921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        case GenericMessage::TYPE_DATA:
1931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            out->printf("<bytes>");
1941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            break;
1951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
1961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
1971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic void
1991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoprint_message(Out* out, Descriptor const* descriptor, GenericMessage const* message)
2001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
2011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    out->printf("%s {\n", descriptor->name().c_str());
2021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    out->indent();
2031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    int const N = descriptor->field_count();
2051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    for (int i=0; i<N; i++) {
2061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        FieldDescriptor const* field = descriptor->field(i);
2071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        int fieldId = field->number();
2091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        bool repeated = field->label() == FieldDescriptor::LABEL_REPEATED;
2101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        FieldDescriptor::Type type = field->type();
2111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        GenericMessage::const_iterator_pair it = message->find(fieldId);
2121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        out->printf("%s=", field->name().c_str());
2141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (repeated) {
2151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (it.first != it.second) {
2161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                out->printf("[");
2171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if (type == FieldDescriptor::TYPE_MESSAGE
2181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        || type == FieldDescriptor::TYPE_STRING
2191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        || type == FieldDescriptor::TYPE_BYTES) {
2201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    out->printf("\n");
2211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
2221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                out->indent();
2231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                for (GenericMessage::const_iterator_pair it = message->find(fieldId);
2251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        it.first != it.second; it.first++) {
2261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    print_value(out, field, it.first->second);
2271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    if (type == FieldDescriptor::TYPE_MESSAGE
2281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                            || type == FieldDescriptor::TYPE_STRING
2291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                            || type == FieldDescriptor::TYPE_BYTES) {
2301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        out->printf("\n");
2311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    }
2321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
2331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                out->dedent();
2351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                out->printf("]");
2361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            } else {
2371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                out->printf("[]");
2381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
2391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else {
2401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (it.first != it.second) {
2411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                print_value(out, field, it.first->second);
2421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            } else {
2431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                switch (type) {
2441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    case FieldDescriptor::TYPE_BOOL:
2451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        out->printf("false");
2461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        break;
2471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    case FieldDescriptor::TYPE_STRING:
2481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    case FieldDescriptor::TYPE_MESSAGE:
2491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        out->printf("");
2501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        break;
2511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    case FieldDescriptor::TYPE_ENUM:
2521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        out->printf("%s", field->default_value_enum()->name().c_str());
2531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        break;
2541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    default:
2551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        out->printf("0");
2561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        break;
2571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
2581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
2591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
2601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        out->printf("\n");
2611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
2621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    out->dedent();
2631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    out->printf("}");
2641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
2651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato// ================================================================================
2671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic uint8_t*
2681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratowrite_raw_varint(uint8_t* buf, uint32_t val)
2691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
2701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    uint8_t* p = buf;
2711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    while (true) {
2721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if ((val & ~0x7F) == 0) {
2731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            *p++ = (uint8_t)val;
2741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return p;
2751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else {
2761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            *p++ = (uint8_t)((val & 0x7F) | 0x80);
2771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            val >>= 7;
2781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
2791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
2801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
2811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic int
2831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratowrite_all(int fd, uint8_t const* buf, size_t size)
2841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
2851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    while (size > 0) {
2861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        ssize_t amt = ::write(fd, buf, size);
2871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (amt < 0) {
2881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return errno;
2891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
2901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        size -= amt;
2911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        buf += amt;
2921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
2931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    return 0;
2941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
2951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic int
2971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoadb_incident_workaround(const char* adbSerial, const vector<string>& sections)
2981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
2991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    const int maxAllowedSize = 20 * 1024 * 1024; // 20MB
3001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    uint8_t* buffer = (uint8_t*)malloc(maxAllowedSize);
3011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    for (vector<string>::const_iterator it=sections.begin(); it!=sections.end(); it++) {
3031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        Descriptor const* descriptor = IncidentProto::descriptor();
3041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        FieldDescriptor const* field;
3051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // Get the name and field id.
3071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        string name = *it;
3081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        char* end;
3091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        int id = strtol(name.c_str(), &end, 0);
3101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (*end == '\0') {
3111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // If it's an id, find out the string.
3121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            field = descriptor->FindFieldByNumber(id);
3131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (field == NULL) {
3141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                fprintf(stderr, "Unable to find field number: %d\n", id);
3151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return 1;
3161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
3171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            name = field->name();
3181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else {
3191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // If it's a string, find out the id.
3201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            field = descriptor->FindFieldByName(name);
3211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (field == NULL) {
3221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                fprintf(stderr, "Unable to find field: %s\n", name.c_str());
3231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return 1;
3241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
3251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            id = field->number();
3261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
3271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        int pfd[2];
3291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (pipe(pfd) != 0) {
3301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            fprintf(stderr, "pipe failed: %s\n", strerror(errno));
3311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return 1;
3321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
3331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        pid_t pid = fork();
3351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (pid == -1) {
3361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            fprintf(stderr, "fork failed: %s\n", strerror(errno));
3371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return 1;
3381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else if (pid == 0) {
3391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // child
3401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            dup2(pfd[1], STDOUT_FILENO);
3411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            close(pfd[0]);
3421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            close(pfd[1]);
3431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            char const** args = (char const**)malloc(sizeof(char*) * 8);
3451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            int argpos = 0;
3461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = "adb";
3471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (adbSerial != NULL) {
3481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                args[argpos++] = "-s";
3491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                args[argpos++] = adbSerial;
3501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
3511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = "shell";
3521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = "dumpsys";
3531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = name.c_str();
3541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = "--proto";
3551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = NULL;
3561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            execvp(args[0], (char*const*)args);
3571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            fprintf(stderr, "execvp failed: %s\n", strerror(errno));
35889547ce0178d5b5b66badc5a422cdbecc9ddac34Yunlian Jiang            free(args);
3591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return 1;
3601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else {
3611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // parent
3621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            close(pfd[1]);
3631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            size_t size = 0;
3651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            while (size < maxAllowedSize) {
3661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                ssize_t amt = read(pfd[0], buffer + size, maxAllowedSize - size);
3671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if (amt == 0) {
3681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    break;
3691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                } else if (amt == -1) {
3701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    fprintf(stderr, "read error: %s\n", strerror(errno));
3711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    return 1;
3721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
3731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                size += amt;
3741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
3751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            int status;
3771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            do {
3781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                waitpid(pid, &status, 0);
3791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            } while (!WIFEXITED(status));
3801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (WEXITSTATUS(status) != 0) {
3811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return WEXITSTATUS(status);
3821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
3831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (size > 0) {
3851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                uint8_t header[20];
3861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                uint8_t* p = write_raw_varint(header, (id << 3) | 2);
3871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                p = write_raw_varint(p, size);
3881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                int err = write_all(STDOUT_FILENO, header, p-header);
3891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if (err != 0) {
3901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    fprintf(stderr, "write error: %s\n", strerror(err));
3911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    return 1;
3921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
3931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                err = write_all(STDOUT_FILENO, buffer, size);
3941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if (err != 0) {
3951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    fprintf(stderr, "write error: %s\n", strerror(err));
3961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    return 1;
3971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
3981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
3991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
4001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            close(pfd[0]);
4011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
4021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
4031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
40489547ce0178d5b5b66badc5a422cdbecc9ddac34Yunlian Jiang    free(buffer);
4051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    return 0;
4061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
4071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
4081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato// ================================================================================
4091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic void
4101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratousage(FILE* out)
4111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
4121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "usage: incident_report -i INPUT [-o OUTPUT]\n");
4131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "\n");
4141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "Pretty-prints an incident report protobuf file.\n");
4151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "  -i INPUT    the input file. INPUT may be '-' to use stdin\n");
4161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "  -o OUTPUT   the output file. OUTPUT may be '-' or omitted to use stdout\n");
4171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "\n");
4181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "\n");
4191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "usage: incident_report [-o OUTPUT] [-t|b] [-s SERIAL] [SECTION...]\n");
4201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "\n");
4211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "Take an incident report over adb (which must be in the PATH).\n");
4221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "  -b          output the incident report raw protobuf format\n");
4231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "  -o OUTPUT   the output file. OUTPUT may be '-' or omitted to use stdout\n");
4241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "  -s SERIAL   sent to adb to choose which device, instead of $ANDROID_SERIAL\n");
4251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "  -t          output the incident report in pretty-printed text format\n");
4261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "\n");
4271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "  SECTION     which bugreport sections to print, either the int code of the\n");
4281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "              section in the Incident proto or the field name.  If ommited,\n");
4291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "              the report will contain all fields\n");
4301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    fprintf(out, "\n");
4311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
4321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
4331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoint
4341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratomain(int argc, char** argv)
4351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
4361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    enum { OUTPUT_TEXT, OUTPUT_PROTO } outputFormat = OUTPUT_TEXT;
4371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    const char* inFilename = NULL;
4381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    const char* outFilename = NULL;
4391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    const char* adbSerial = NULL;
4401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    bool adbIncidentWorkaround = true;
4411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    pid_t childPid = -1;
4421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    vector<string> sections;
4431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
4441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    int opt;
4451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    while ((opt = getopt(argc, argv, "bhi:o:s:tw")) != -1) {
4461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        switch (opt) {
4471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case 'b':
4481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                outputFormat = OUTPUT_PROTO;
4491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                break;
4501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case 'i':
4511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                inFilename = optarg;
4521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                break;
4531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case 'o':
4541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                outFilename = optarg;
4551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                break;
4561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case 's':
4571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                adbSerial = optarg;
4581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                break;
4591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case 't':
4601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                outputFormat = OUTPUT_TEXT;
4611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                break;
4621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case 'h':
4631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                usage(stdout);
4641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return 0;
4651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            case 'w':
4661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                adbIncidentWorkaround = false;
4671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                break;
4681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            default:
4691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                usage(stderr);
4701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return 1;
4711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
4721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
4731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
4741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    while (optind < argc) {
4751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        sections.push_back(argv[optind++]);
4761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
4771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
4781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    int inFd;
4791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (inFilename != NULL) {
4801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // translate-only mode - oepn the file or use stdin.
4811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (strcmp("-", inFilename) == 0) {
4821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            inFd = STDIN_FILENO;
4831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else {
4841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            inFd = open(inFilename, O_RDONLY | O_CLOEXEC);
4851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (inFd < 0) {
4861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                fprintf(stderr, "unable to open file for read (%s): %s\n", strerror(errno),
4871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        inFilename);
4881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return 1;
4891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
4901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
4911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    } else {
4921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // pipe mode - run adb shell incident ...
4931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        int pfd[2];
4941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (pipe(pfd) != 0) {
4951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            fprintf(stderr, "pipe failed: %s\n", strerror(errno));
4961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return 1;
4971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
4981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
4991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        childPid = fork();
5001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (childPid == -1) {
5011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            fprintf(stderr, "fork failed: %s\n", strerror(errno));
5021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return 1;
5031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else if (childPid == 0) {
5041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            dup2(pfd[1], STDOUT_FILENO);
5051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            close(pfd[0]);
5061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            close(pfd[1]);
5071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // child
5081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (adbIncidentWorkaround) {
5091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                // TODO: Until the device side incident command is checked in,
5101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                // the incident_report builds the outer Incident proto by hand
5111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                // from individual adb shell dumpsys <service> --proto calls,
5121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                // with a maximum allowed output size.
5131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                return adb_incident_workaround(adbSerial, sections);
5141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
5151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
5161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // TODO: This is what the real implementation will be...
5171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            char const** args = (char const**)malloc(sizeof(char*) * (6 + sections.size()));
5181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            int argpos = 0;
5191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = "adb";
5201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (adbSerial != NULL) {
5211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                args[argpos++] = "-s";
5221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                args[argpos++] = adbSerial;
5231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
5241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = "shell";
5251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = "incident";
5261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            for (vector<string>::const_iterator it=sections.begin(); it!=sections.end(); it++) {
5271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                args[argpos++] = it->c_str();
5281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
5291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            args[argpos++] = NULL;
5301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            execvp(args[0], (char*const*)args);
5311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            fprintf(stderr, "execvp failed: %s\n", strerror(errno));
5321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return 0;
5331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } else {
5341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // parent
5351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            inFd = pfd[0];
5361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            close(pfd[1]);
5371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
5381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
5391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
5401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    int outFd;
5411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (outFilename == NULL || strcmp("-", outFilename) == 0) {
5421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        outFd = STDOUT_FILENO;
5431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    } else {
5441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        outFd = open(outFilename, O_CREAT | O_RDWR, 0666);
5451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (outFd < 0) {
5461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            fprintf(stderr, "unable to open file for write: %s\n", outFilename);
5471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return 1;
5481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
5491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
5501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
5511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    GenericMessage message;
5521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
5531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    Descriptor const* descriptor = IncidentProto::descriptor();
5541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    FileInputStream infile(inFd);
5551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    CodedInputStream in(&infile);
5561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
5571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (!read_message(&in, descriptor, &message)) {
5581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        fprintf(stderr, "unable to read incident\n");
5591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        return 1;
5601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
5611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
5621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    Out out(outFd);
5631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
5641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    print_message(&out, descriptor, &message);
5651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    out.printf("\n");
5661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
5671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (childPid != -1) {
5681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        int status;
5691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        do {
5701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            waitpid(childPid, &status, 0);
5711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        } while (!WIFEXITED(status));
5721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (WEXITSTATUS(status) != 0) {
5731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return WEXITSTATUS(status);
5741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
5751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
5761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
5771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    return 0;
5781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
579