Home | History | Annotate | Download | only in parser
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.loganalysis.parser;
     18 
     19 import com.android.loganalysis.item.IItem;
     20 import com.android.loganalysis.item.LatencyItem;
     21 import com.android.loganalysis.item.TransitionDelayItem;
     22 
     23 import java.io.BufferedReader;
     24 import java.io.IOException;
     25 import java.util.ArrayList;
     26 import java.util.HashMap;
     27 import java.util.List;
     28 import java.util.Map;
     29 import java.util.regex.Matcher;
     30 import java.util.regex.Pattern;
     31 
     32 /**
     33  * Parse the events logs. </p>
     34  */
     35 public class EventsLogParser implements IParser {
     36 
     37     // 09-18 23:56:19.376 1140 1221 I sysui_multi_action:
     38     // [319,51,321,50,322,190,325,670,757,761,758,7,759,1,806,com.google.android.calculator,871,
     39     // com.android.calculator2.Calculator,905,0,945,41]
     40     private static final Pattern SYSUI_TRANSITION_INFO_PATTERN = Pattern.compile(
     41             "^(?<date>[0-9-]*)\\s+(?<time>[0-9:.]*)\\s+\\d+\\s+\\d+ I sysui_multi_action:"
     42                     + " \\[(?<transitioninfo>.*)\\]$");
     43 
     44     // 08-21 17:53:53.876 1053 2135 I sysui_latency: [1,50]
     45     private static final Pattern ACTION_LATENCY = Pattern.compile("^(?<date>[0-9-]*)\\s+"
     46             + "(?<time>[0-9:.]*)\\s+\\d+\\s+\\d+ I sysui_latency: \\[(?<action>.*),"
     47             + "(?<delay>.*)\\]$");
     48 
     49     private static final String DATE = "date";
     50     private static final String TIME = "time";
     51     private static final String TRANSITION_INFO = "transitioninfo";
     52     private static final String PACKAGE_KEY = "806";
     53     private static final String ACTIVITY_KEY = "871";
     54     private static final String TRANSITION_DELAY_KEY = "319";
     55     private static final String STARTING_WINDOW_DELAY_KEY = "321";
     56     private static final String COLD_LAUNCH_KEY = "945";
     57     private static final String WINDOWS_DRAWN_DELAY_KEY = "322";
     58 
     59     @Override
     60     public IItem parse(List<String> lines) {
     61         throw new UnsupportedOperationException("Method has not been implemented in lieu"
     62                 + " of others");
     63     }
     64 
     65     /**
     66      * Parse the transition delay information from the events log.
     67      * @param input
     68      * @return list of transition delay items.
     69      * @throws IOException
     70      */
     71     public List<TransitionDelayItem> parseTransitionDelayInfo(BufferedReader input)
     72             throws IOException {
     73         List<TransitionDelayItem> transitionDelayItems = new ArrayList<TransitionDelayItem>();
     74         String line;
     75         Matcher match = null;
     76         while ((line = input.readLine()) != null) {
     77             if ((match = matches(SYSUI_TRANSITION_INFO_PATTERN, line)) != null) {
     78                 Map<String, String> transitionInfoMap = getTransitionInfoMap(
     79                         match.group(TRANSITION_INFO));
     80                 if (transitionInfoMap.containsKey(TRANSITION_DELAY_KEY)) {
     81                     TransitionDelayItem delayItem = new TransitionDelayItem();
     82                     if (null != transitionInfoMap.get(PACKAGE_KEY)
     83                             && null != transitionInfoMap.get(ACTIVITY_KEY)
     84                             && null != transitionInfoMap.get(TRANSITION_DELAY_KEY)
     85                             && null != transitionInfoMap.get(WINDOWS_DRAWN_DELAY_KEY)) {
     86                         delayItem.setComponentName(transitionInfoMap.get(PACKAGE_KEY) + "/"
     87                                 + transitionInfoMap.get(ACTIVITY_KEY));
     88                         delayItem.setTransitionDelay(Long.parseLong(transitionInfoMap
     89                                 .get(TRANSITION_DELAY_KEY)));
     90                         delayItem.setDateTime(String.format("%s %s", match.group(DATE),
     91                                 match.group(TIME)));
     92                         delayItem.setWindowDrawnDelay(
     93                                 Long.parseLong(transitionInfoMap.get(WINDOWS_DRAWN_DELAY_KEY)));
     94                     }
     95                     if (transitionInfoMap.containsKey(COLD_LAUNCH_KEY)) {
     96                         if (null != transitionInfoMap.get(STARTING_WINDOW_DELAY_KEY)) {
     97                             delayItem.setStartingWindowDelay(Long.parseLong(transitionInfoMap
     98                                     .get(STARTING_WINDOW_DELAY_KEY)));
     99                         }
    100                     }
    101                     transitionDelayItems.add(delayItem);
    102                 }
    103             }
    104         }
    105         return transitionDelayItems;
    106     }
    107 
    108     /**
    109      * Split the transition info string in to key, values and return a map.
    110      * @param transitionInfo transition info map in hey value format.
    111      * @return
    112      */
    113     public Map<String, String> getTransitionInfoMap(String transitionInfo) {
    114         String[] transitionSplit = transitionInfo.split(",");
    115         Map<String, String> transitionInfoMap = new HashMap<>();
    116         if (transitionSplit.length % 2 == 0) {
    117             for (int i = 0; i < transitionSplit.length; i = i + 2) {
    118                 transitionInfoMap.put(transitionSplit[i], transitionSplit[i + 1]);
    119             }
    120         }
    121         return transitionInfoMap;
    122     }
    123 
    124     /**
    125      * Method to parse the latency information from the events log
    126      * @param input
    127      * @return
    128      * @throws IOException
    129      */
    130     public List<LatencyItem> parseLatencyInfo(BufferedReader input) throws IOException {
    131         List<LatencyItem> latencyItems = new ArrayList<LatencyItem>();
    132         String line;
    133         while ((line = input.readLine()) != null) {
    134             Matcher match = null;
    135             if (((match = matches(ACTION_LATENCY, line))) != null) {
    136                 LatencyItem latencyItem = new LatencyItem();
    137                 latencyItem.setActionId(Integer.parseInt(match.group("action")));
    138                 latencyItem.setDelay(Long.parseLong(match.group("delay")));
    139                 latencyItems.add(latencyItem);
    140             }
    141         }
    142         return latencyItems;
    143     }
    144 
    145     /**
    146      * Checks whether {@code line} matches the given {@link Pattern}.
    147      *
    148      * @return The resulting {@link Matcher} obtained by matching the {@code line} against
    149      *         {@code pattern}, or null if the {@code line} does not match.
    150      */
    151     private static Matcher matches(Pattern pattern, String line) {
    152         Matcher ret = pattern.matcher(line);
    153         return ret.matches() ? ret : null;
    154     }
    155 
    156 }
    157