1 /* 2 * Copyright (C) 2019 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.server.protolog.common; 18 19 import java.util.ArrayList; 20 import java.util.List; 21 22 /** 23 * Represents a type of logged data encoded in the proto. 24 */ 25 public class LogDataType { 26 // When updating this list make sure to update bitmask conversion methods accordingly. 27 // STR type should be the first in the enum in order to be the default type. 28 public static final int STRING = 0b00; 29 public static final int LONG = 0b01; 30 public static final int DOUBLE = 0b10; 31 public static final int BOOLEAN = 0b11; 32 33 private static final int TYPE_WIDTH = 2; 34 private static final int TYPE_MASK = 0b11; 35 36 /** 37 * Creates a bitmask representing a list of data types. 38 */ logDataTypesToBitMask(List<Integer> types)39 public static int logDataTypesToBitMask(List<Integer> types) { 40 if (types.size() > 16) { 41 throw new BitmaskConversionException("Too many log call parameters " 42 + "- max 16 parameters supported"); 43 } 44 int mask = 0; 45 for (int i = 0; i < types.size(); i++) { 46 int x = types.get(i); 47 mask = mask | (x << (i * TYPE_WIDTH)); 48 } 49 return mask; 50 } 51 52 /** 53 * Decodes a bitmask to a list of LogDataTypes of provided length. 54 */ bitmaskToLogDataType(int bitmask, int index)55 public static int bitmaskToLogDataType(int bitmask, int index) { 56 if (index > 16) { 57 throw new BitmaskConversionException("Max 16 parameters allowed"); 58 } 59 return (bitmask >> (index * TYPE_WIDTH)) & TYPE_MASK; 60 } 61 62 /** 63 * Creates a list of LogDataTypes from a message format string. 64 */ parseFormatString(String messageString)65 public static List<Integer> parseFormatString(String messageString) { 66 ArrayList<Integer> types = new ArrayList<>(); 67 for (int i = 0; i < messageString.length(); ) { 68 if (messageString.charAt(i) == '%') { 69 if (i + 1 >= messageString.length()) { 70 throw new InvalidFormatStringException("Invalid format string in config"); 71 } 72 switch (messageString.charAt(i + 1)) { 73 case 'b': 74 types.add(LogDataType.BOOLEAN); 75 break; 76 case 'd': 77 case 'o': 78 case 'x': 79 types.add(LogDataType.LONG); 80 break; 81 case 'f': 82 case 'e': 83 case 'g': 84 types.add(LogDataType.DOUBLE); 85 break; 86 case 's': 87 types.add(LogDataType.STRING); 88 break; 89 case '%': 90 break; 91 default: 92 throw new InvalidFormatStringException("Invalid format string field" 93 + " %${messageString[i + 1]}"); 94 } 95 i += 2; 96 } else { 97 i += 1; 98 } 99 } 100 return types; 101 } 102 } 103