1#!/usr/bin/python
2
3#
4# Copyright (C) 2019 The Android Open Source Project
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#      http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19"""
20Parses a given bugreport for specific device Id.
21If parsing is successful, then generate respective
22JSON configuration.
23
24"""
25import json
26import os
27import re
28import sys
29import zipfile
30
31"""
32Store static camera characteristics in given
33JSON configuration file.
34"""
35def storeJsonConfigration(filePath, chars):
36    with open(filePath, 'w') as jsonFile:
37        json.dump(chars, jsonFile, sort_keys=True, indent=1)
38
39"""
40Parse media.camera dump section and populate the camera
41characteristics list of dictionaries.
42"""
43def parseCameraDump(deviceId, cameraDumpPath, tagList):
44    deviceRegExp = "== Camera HAL device device@[0-9]+\.[0-9]+/{0} \(v3.".format(deviceId)
45    physicalDeviceRegExp = "Physical camera [0-9] characteristics:"
46    tagRegExp = " {4}android[a-zA-Z0-9\.]+ \([a-z0-9]+\): "
47    tagValueRegExp = "[^a-zA-Z0-9-\._]"
48    expandedTagsRegExp = " \(.*?\)"
49    expandedMetadataTags = ["android.request.availableRequestKeys",
50                            "android.request.availableResultKeys",
51                            "android.request.availableSessionKeys",
52                            "android.request.availableCharacteristicsKeys",
53                            "android.request.availablePhysicalCameraRequestKeys"]
54    with open(cameraDumpPath, "r") as file:
55        devices = re.split(deviceRegExp, file.read())
56        if len(devices) != 3 and len(devices) != 2:
57            print("Camera device id: {0} not found".format(deviceId))
58            sys.exit()
59
60        physicalDevices = re.split(physicalDeviceRegExp, devices[1])
61        physicalIdx = 0
62        for physicalDevice in physicalDevices:
63            physicalIdx += 1
64            tags = re.split(tagRegExp, physicalDevice)
65            tagsContent = re.findall(tagRegExp, physicalDevice)
66            i = 0;
67            parseEnd = False
68            deviceChars = dict()
69            for tag in tags[1:]:
70                if parseEnd:
71                    break
72
73                lines = tag.splitlines()
74                if len(lines) < 2:
75                    print("Empty tag entry, skipping!")
76                    continue
77                tagName = tagsContent[i].split()[0]
78
79                if tagName is None or len(tagName) < 1:
80                    print("Invalid tag found, skipping!")
81                    continue
82
83                i += 1
84                for line in lines[1:]:
85                    if line.startswith('== Camera HAL device device'):
86                        parseEnd = True
87                        break
88
89                    values = re.split(r' {8}', line)
90                    if len(values) == 2:
91                        # For all the tags which have expanded values of the tag ids, remove the
92                        # expanded value in round brackets when generating the json file.
93                        if tagName in expandedMetadataTags:
94                            # replace everything between '<space>(' and ')' with an empty string.
95                            values[1] = re.sub(expandedTagsRegExp, "", values[1])
96                        key = tagName
97                        tagValues = list(filter(None, re.split(tagValueRegExp, values[1])))
98                        if key in deviceChars:
99                            deviceChars[key] = deviceChars[key] + tagValues
100                        else:
101                            deviceChars[key] = tagValues
102                    else:
103                        break
104            tagList.append(deviceChars)
105    os.remove(cameraDumpPath)
106
107if __name__ == '__main__':
108    argc = len(sys.argv)
109    deviceId = ""
110    bugreportPath = ""
111    configPath = ""
112    if argc >= 4:
113        bugreportPath = str(sys.argv[1])
114        deviceId = str(sys.argv[2])
115        configPath = str(sys.argv[3])
116    else:
117        print("Usage: parse_bugreport.py PathToBugreport DeviceId JSONConfigurationPath")
118        sys.exit();
119
120    with zipfile.ZipFile(bugreportPath) as bugzip:
121        cameraDumpFile = ""
122        for name in bugzip.namelist():
123            if re.match("bugreport", name) is not None:
124                cameraDumpFile = name
125                break
126
127        if len(cameraDumpFile) == 0:
128            print("Camera dump not found in bugreport!")
129            sys.exit()
130
131        tagList = list()
132        parseCameraDump(deviceId, bugzip.extract(cameraDumpFile), tagList)
133        storeJsonConfigration(configPath, tagList)
134
135