• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef ANDROID_FRAMEWORK_ML_NN_RUNTIME_TEST_FUZZING_OPERATION_MANAGER_H
18 #define ANDROID_FRAMEWORK_ML_NN_RUNTIME_TEST_FUZZING_OPERATION_MANAGER_H
19 
20 #include <functional>
21 #include <map>
22 #include <string>
23 #include <vector>
24 
25 #include "TestNeuralNetworksWrapper.h"
26 #include "fuzzing/RandomGraphGenerator.h"
27 #include "fuzzing/RandomVariable.h"
28 
29 namespace android {
30 namespace nn {
31 namespace fuzzing_test {
32 
33 using test_wrapper::Type;
34 
35 struct OperandSignature {
36     // Possible values are [INPUT | CONST | OUTPUT].
37     // If CONST, the generator will avoid feeding the operand with another operation’s output.
38     RandomOperandType type;
39 
40     // The operand constructor is invoked before the operation constructor. This is for
41     // setting the data type, quantization parameters, or optionally the scalar value.
42     std::function<void(Type, uint32_t, RandomOperand*)> constructor = nullptr;
43 
44     // The operand finalizer is invoked after the graph structure is frozen but before the operation
45     // finalizer. This is for generating the buffer values for the operand.
46     std::function<void(RandomOperand*)> finalizer = nullptr;
47 };
48 
49 enum class HalVersion : int32_t { V1_0 = 0, V1_1 = 1, V1_2 = 2 };
50 
51 // A filter applied to OperationSignatures. An OperationSignature is filtered out if the opType, all
52 // of supportedDataTypes, all of supportedRanks, or the version does not match with any entry in the
53 // corresponding vector in the filter. Use empty vector in the filter for "no filter".
54 //
55 // E.g.
56 // - To get all 1.0 ADD operation signatures
57 //       {.opcodes = {ANEURALNETWORKS_ADD}, .versions = {HalVersion::V1_0}}
58 //
59 // - To get all 1.0 and 1.1 operations with rank 2 or 4
60 //       {.ranks = {2, 4}, .versions = {HalVersion::V1_0, HalVersion::V1_1}}
61 //
62 struct OperationFilter {
63     std::vector<ANeuralNetworksOperationType> opcodes;
64     std::vector<Type> dataTypes;
65     std::vector<uint32_t> ranks;
66     std::vector<HalVersion> versions;
67 };
68 
69 struct OperationSignature {
70     // Defines the basic metadata of an operation filterable by OperationFilter.
71     // Upon generation, the random graph generator will randomly choose a supported data type and
72     // rank, and pass the information to the constructors.
73     ANeuralNetworksOperationType opType;
74     std::vector<Type> supportedDataTypes;
75     std::vector<uint32_t> supportedRanks;
76     HalVersion version;
77 
78     // OperandSignatures for inputs and outputs.
79     std::vector<OperandSignature> inputs;
80     std::vector<OperandSignature> outputs;
81 
82     // The operation constructor is invoked after the inputs and outputs constructor. This is for
83     // setting the dimension relationship of random operands, and/or generating parameter values at
84     // the operation level, e.g. a parameter depends on or affects another operand in the same
85     // operation.
86     std::function<void(Type, uint32_t, RandomOperation*)> constructor = nullptr;
87 
88     // The operation finalizer is invoked after the graph structure is frozen and inputs and outputs
89     // constructors are invoked. This is for generating operand buffers at the operation level, e.g.
90     // an operand buffer that depends on another operand in the same operation.
91     std::function<void(RandomOperation*)> finalizer = nullptr;
92 
93     // Check if the OperationSignature matches with the filter. Shrink supported* if needed.
94     bool matchFilter(const OperationFilter& filter);
95 };
96 
97 // A manager manages all available OperationSignatures.
98 class OperationManager {
99    public:
100     // Returns the singleton manager.
101     static OperationManager* get();
102 
103     // Add the signature to the managed mOperationSignatures if matches with mFilter.
104     void addSignature(const std::string& name, const OperationSignature& signature);
105 
106     // Reinitialize mFilteredSignatures by applying a filter to all of the operation signatures in
107     // mOperationSignatures.
108     void applyFilter(const OperationFilter& filter);
109 
110     // Randomly returns a valid OperationSignature. RandomGraphGenerator uses this method to
111     // generate a random list of operations in the graph.
112     const OperationSignature& getRandomOperation() const;
113 
114    protected:
115     OperationManager() = default;
116 
117     // Contains all operation signatures defined in operation_signatures/*.cpp.
118     // The signatures are sorted by name to ensure a predictable order.
119     std::map<std::string, const OperationSignature> mOperationSignatures;
120 
121     // A subset of mOperationSignatures using by the random graph generator.
122     // This vector should be initialized by applyFilter() before generating the graph.
123     std::vector<OperationSignature> mFilteredSignatures;
124 };
125 
126 }  // namespace fuzzing_test
127 }  // namespace nn
128 }  // namespace android
129 
130 #endif  // ANDROID_FRAMEWORK_ML_NN_RUNTIME_TEST_FUZZING_OPERATION_MANAGER_H
131