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
GetKeyIndex(uint8_t b)29 int GetKeyIndex(uint8_t b) {
30 int type = b & 0x7;
31 if (type != 0) return kKeyError;
32 return b >> 3;
33 }
34
GetBase128IntegerFromByteStream(const std::vector<uint8_t> & bytes,int & index)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
WriteBase128IntToStream(uint64_t x,std::vector<uint8_t> & bytes)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
DecodeAnnotationSerialization(const SerializedAnnotation & ser,const std::vector<int> & radix_mult)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
SerializeAnnotationId(uint64_t id,SerializedAnnotation & ser,const std::vector<int> & radix_mult)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
SetUpAnnotationRadixes(std::vector<int> & radix_mult,const std::vector<int> & enum_sizes)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