1 /* 2 * Copyright 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 #include "annotation_util.h" 18 19 #include <cstdlib> 20 21 #define LOG_TAG "TuningFork" 22 #include "Log.h" 23 24 namespace annotation_util { 25 26 typedef uint64_t AnnotationId; 27 28 // This is a protobuf 1-based index 29 int GetKeyIndex(uint8_t b) { 30 int type = b & 0x7; 31 if (type != 0) return kKeyError; 32 return b >> 3; 33 } 34 35 uint64_t GetBase128IntegerFromByteStream(const std::vector<uint8_t> &bytes, int &index) { 36 uint64_t m = 0; 37 uint64_t r = 0; 38 while (index < bytes.size() && m <= (64 - 7)) { 39 auto b = bytes[index]; 40 r |= (((uint64_t) b) & 0x7f) << m; 41 if ((b & 0x80) != 0) m += 7; 42 else return r; 43 ++index; 44 } 45 return kStreamError; 46 } 47 48 void WriteBase128IntToStream(uint64_t x, std::vector<uint8_t> &bytes) { 49 do { 50 uint8_t a = x & 0x7f; 51 int b = x & 0xffffffffffffff80; 52 if (b) { 53 bytes.push_back(a | 0x80); 54 x >>= 7; 55 } else { 56 bytes.push_back(a); 57 return; 58 } 59 } while(x); 60 } 61 62 AnnotationId DecodeAnnotationSerialization(const SerializedAnnotation &ser, 63 const std::vector<int>& radix_mult) { 64 AnnotationId result = 0; 65 for (int i = 0; i < ser.size(); ++i) { 66 int key = GetKeyIndex(ser[i]); 67 if (key == kKeyError) 68 return kAnnotationError; 69 // Convert to 0-based index 70 --key; 71 if (key >= radix_mult.size()) 72 return kAnnotationError; 73 ++i; 74 if (i >= ser.size()) 75 return kAnnotationError; 76 uint64_t value = GetBase128IntegerFromByteStream(ser, i); 77 if (value == kStreamError) 78 return kAnnotationError; 79 // Check the range of the value 80 if (value == 0 || value >= radix_mult[key]) 81 return kAnnotationError; 82 // We don't allow enums with more that 255 values 83 if (value > 0xff) 84 return kAnnotationError; 85 if (key > 0) 86 result += radix_mult[key - 1] * value; 87 else 88 result += value; 89 } 90 return result; 91 } 92 93 int SerializeAnnotationId(uint64_t id, SerializedAnnotation& ser, 94 const std::vector<int>& radix_mult) { 95 int err = 0; 96 uint64_t x = id; 97 for (int i = 0; i < radix_mult.size(); ++i) { 98 auto r = ::div(x, radix_mult[i]); 99 int value = r.rem; 100 if (value > 0) { 101 int key = (i + 1) << 3; 102 ser.push_back(key); 103 WriteBase128IntToStream(value, ser); 104 } 105 x = r.quot; 106 } 107 return err; 108 } 109 110 void SetUpAnnotationRadixes( std::vector<int>& radix_mult, 111 const std::vector<int>& enum_sizes) { 112 ALOGV("Settings::annotation_enum_size"); 113 for(int i=0; i< enum_sizes.size();++i) { 114 ALOGV("%d", enum_sizes[i]); 115 } 116 int n = enum_sizes.size(); 117 if (n == 0) { 118 // With no annotations, we just have 1 possible prong per key 119 radix_mult.resize(1); 120 radix_mult[0] = 1; 121 } else { 122 radix_mult.resize(n); 123 int r = 1; 124 for (int i = 0; i < n; ++i) { 125 r *= enum_sizes[i] + 1; 126 radix_mult[i] = r; 127 } 128 } 129 } 130 131 } // namespace annotation_util 132