First implementation of the Neural Networks API.

This first version can run a simple query on the CPU either
via the fallback path or through a simulated driver.

This code has many deficiencies: single threaded, not all
validation are done, not going through HIDL, and not
enough unit tests.  Expect more changes!

Test: Compiled and ran the unit tests

Change-Id: I9f6a485a2e7207aeb5f91a2904dcb4b7fd8a6f65
diff --git a/common/Android.bp b/common/Android.bp
new file mode 100644
index 0000000..8f00067
--- /dev/null
+++ b/common/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_library_static {
+    name: "libneuralnetworks_common",
+    defaults: ["neuralnetworks_defaults"],
+    host_supported: true,
+    export_include_dirs: ["include"],
+
+    srcs: [
+        "CpuExecutor.cpp",
+        "Operations.cpp",
+        "OperationsUtils.cpp",
+        "Utils.cpp",
+    ],
+
+    header_libs: [
+        "libneuralnetworks_headers",
+    ],
+}
diff --git a/common/CpuExecutor.cpp b/common/CpuExecutor.cpp
new file mode 100644
index 0000000..3539edc
--- /dev/null
+++ b/common/CpuExecutor.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CpuExecutor"
+
+#include "CpuExecutor.h"
+
+#include "Model.h"
+#include "NeuralNetworks.h"
+#include "Operations.h"
+
+namespace android {
+namespace nn {
+
+// If we don't have a buffer, allocate it.
+static bool allocateIfNeeded(RunTimeOperandInfo* info) {
+    if (info->buffer == nullptr) {
+        uint32_t length =
+                sizeOfData(info->shape.type,
+                           Range<uint32_t>(info->shape.numberOfDimensions, info->shape.dimensions));
+        info->buffer = malloc(length);
+    }
+    return true;
+}
+
+CpuExecutor::CpuExecutor(const IModel* model, const std::vector<InputOutputInfo>& modelInputs,
+                         const std::vector<InputOutputInfo>& modelOutputs)
+      : mModel(model) {
+    mModel->copyDimensionStorage(&mDimensions);
+
+    const Range<OperandEntry> modelOperands = model->getOperands();
+    const size_t count = modelOperands.count();
+    mOperands.resize(count);
+    for (size_t i = 0; i < count; i++) {
+        const OperandEntry& from = modelOperands[i];
+        RunTimeOperandInfo& to = mOperands[i];
+        to.shape.type = from.type;
+        to.shape.numberOfDimensions = from.dimensions.count;
+        // It's safe to take the address. The size of mDimensions won't change.
+        to.shape.dimensions = &mDimensions[from.dimensions.offset];
+        if (from.location.pool == LOCATION_AT_RUN_TIME) {
+            to.buffer = nullptr;
+            to.numberOfUsesLeft = from.numberOfConsumers;
+        } else if (from.location.pool == LOCATION_SAME_BLOCK) {
+            to.buffer = const_cast<void*>(mModel->getDataPointer(from.location.offset));
+            to.numberOfUsesLeft = 0;
+        } else {
+            // TODO: Revisit when we add support for multiple pools.
+            nnAssert(false);
+        }
+        to.length = from.length;
+    }
+
+    for (uint32_t i = 0; i < modelInputs.size(); i++) {
+        overrideOperand(mModel->getInputOperandIndex(i), modelInputs[i]);
+    }
+    for (uint32_t i = 0; i < modelOutputs.size(); i++) {
+        overrideOperand(mModel->getOutputOperandIndex(i), modelOutputs[i]);
+    }
+}
+
+int CpuExecutor::run() {
+    // The model has serialized the operation in execution order.
+    for (const auto& operation : mModel->getOperations()) {
+        int n = executeOperation(operation);
+        if (n != ANEURALNETWORKS_NO_ERROR) {
+            return n;
+        }
+    }
+    return ANEURALNETWORKS_NO_ERROR;
+}
+
+void CpuExecutor::overrideOperand(uint32_t operandIndex, const InputOutputInfo& from) {
+    RunTimeOperandInfo& to = mOperands[operandIndex];
+    if (from.dimensionChanged) {
+        nnAssert(to.shape.numberOfDimensions == from.dimensions.size());
+        for (uint32_t i = 0; i < to.shape.numberOfDimensions; i++) {
+            to.shape.dimensions[i] = from.dimensions[i];
+        }
+    }
+    nnAssert(to.buffer == nullptr);
+    to.buffer = from.buffer;
+    to.length = from.length;
+    to.numberOfUsesLeft = 0;
+}
+
+void CpuExecutor::freeNoLongerUsedOperands(const Range<uint32_t>& inputs) {
+    for (uint32_t i : inputs) {
+        auto& info = mOperands[i];
+        // Check if it's a static or model input/output.
+        if (info.numberOfUsesLeft == 0) {
+            continue;
+        }
+        nnAssert(mModel->getOperands()[i].location.pool == LOCATION_AT_RUN_TIME);
+        info.numberOfUsesLeft--;
+        if (info.numberOfUsesLeft == 0) {
+            auto* buffer = mOperands[i].buffer;
+            nnAssert(buffer != nullptr);
+            free(buffer);
+            buffer = nullptr;
+        }
+    }
+}
+
+int CpuExecutor::executeOperation(const OperationEntry& operation) {
+    ALOGI("Executing %s", getOperationName(operation.opCode));
+    const Range<uint32_t> ins = mModel->getOperandIndexes(operation.inputs);
+    const Range<uint32_t> outs = mModel->getOperandIndexes(operation.outputs);
+    bool success = false;
+
+    // Function to verify that the number of input and output parameters
+    // matches what is expected.
+    auto parameterCountIs = [&ins, &outs, &operation](uint32_t expectedIns,
+                                                      uint32_t expectedOuts) -> bool {
+        if (ins.count() != expectedIns || outs.count() != expectedOuts) {
+            ALOGE("%s: Invalid number of ins %u/%u and outs %u/%u",
+                  getOperationName(operation.opCode), ins.count(), expectedIns, outs.count(),
+                  expectedOuts);
+            return false;
+        }
+        return true;
+    };
+
+    switch (static_cast<OperatorType>(operation.opCode)) {
+        case OperatorType::ADD_FLOAT32: {
+            if (!parameterCountIs(2, 1)) {
+                return ANEURALNETWORKS_BAD_DATA;
+            }
+            const RunTimeOperandInfo& in1 = mOperands[ins[0]];
+            const RunTimeOperandInfo& in2 = mOperands[ins[1]];
+            RunTimeOperandInfo& out = mOperands[outs[0]];
+
+            success = addTensorsFloat32Prepare(in1.shape, in2.shape, &out.shape) &&
+                    allocateIfNeeded(&out) &&
+                    addTensorsFloat32(reinterpret_cast<const float*>(in1.buffer),
+                                      reinterpret_cast<const float*>(in2.buffer),
+                                      reinterpret_cast<float*>(out.buffer), in1.shape);
+        } break;
+        default:
+            nnAssert(false);
+            break;
+    }
+    if (!success) {
+        ALOGE("%s failed.", getOperationName(operation.opCode));
+        return ANEURALNETWORKS_OP_FAILED;
+    }
+
+    freeNoLongerUsedOperands(ins);
+    return ANEURALNETWORKS_NO_ERROR;
+}
+
+} // namespace nn
+} // namespace android
diff --git a/common/Operations.cpp b/common/Operations.cpp
new file mode 100644
index 0000000..7e727ec
--- /dev/null
+++ b/common/Operations.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Contains the implementation of the operations.
+
+#define LOG_TAG "Operations"
+
+#include "Operations.h"
+#include "OperationsUtils.h"
+
+namespace android {
+namespace nn {
+
+bool addTensorsFloat32Prepare(const Shape& in1, const Shape& in2, Shape* out1) {
+    return SameShape(in1, in2) && SetShape(in1, out1);
+}
+
+bool addTensorsFloat32(const float* in1, const float* in2, float* out, const Shape& shape) {
+    uint32_t count = getNumberOfElements(shape);
+    for (size_t i = 0; i < count; i++) {
+        *(out++) = *(in1++) + *(in2++);
+    }
+    return true;
+}
+
+}  // namespace nn
+}  // namespace android
diff --git a/common/OperationsUtils.cpp b/common/OperationsUtils.cpp
new file mode 100644
index 0000000..e9c232d
--- /dev/null
+++ b/common/OperationsUtils.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OperationsUtils"
+
+#include "OperationsUtils.h"
+#include "Utils.h"
+
+namespace android {
+namespace nn {
+
+bool SameShape(const Shape& in1, const Shape& in2) {
+    if (in1.type != in2.type || in1.numberOfDimensions != in2.numberOfDimensions) {
+        return false;
+    }
+    for (uint32_t i = 0; i < in1.numberOfDimensions; i++) {
+        if (in1.dimensions[i] != in2.dimensions[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SetShape(const Shape& in, const Shape* out) {
+    if (in.type != out->type || in.numberOfDimensions != out->numberOfDimensions) {
+        return false;
+    }
+    for (uint32_t i = 0; i < in.numberOfDimensions; i++) {
+        out->dimensions[i] = in.dimensions[i];
+    }
+    return true;
+}
+
+uint32_t getNumberOfElements(const Shape& shape) {
+    uint32_t count = 1;
+    for (uint32_t i = 0; i < shape.numberOfDimensions; i++) {
+        count *= shape.dimensions[i];
+    }
+    return count;
+}
+
+}  // namespace nn
+}  // namespace android
diff --git a/common/Utils.cpp b/common/Utils.cpp
new file mode 100644
index 0000000..55f7726
--- /dev/null
+++ b/common/Utils.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Utils"
+
+#include "Utils.h"
+
+#include "NeuralNetworks.h"
+
+namespace android {
+namespace nn {
+
+const char* typeNames[ANEURALNETWORKS_NUMBER_DATA_TYPES] = {
+            "FLOAT16",
+            "FLOAT32",
+            "INT8",
+            "UINT8",
+            "INT16",
+            "UINT16",
+            "INT32",
+            "UINT32",
+            "TENSOR_FLOAT16",
+            "TENSOR_FLOAT32",
+            "TENSOR_SIMMETRICAL_QUANT8",
+};
+
+const char* errorNames[] = {
+            "NO_ERROR",        "OUT_OF_MEMORY", "INCOMPLETE", "NULL", "BAD_DATA",
+            "NOT_IMPLEMENTED",  // TODO remove
+};
+
+const char* kOperationNames[ANEURALNETWORKS_NUMBER_OPERATION_TYPES] = {
+            "AVERAGE_POOL_FLOAT32",
+            "CONCATENATION_FLOAT32",
+            "CONV_FLOAT32",
+            "DEPTHWISE_CONV_FLOAT32",
+            "MAX_POOL_FLOAT32",
+            "L2_POOL_FLOAT32",
+            "DEPTH_TO_SPACE_FLOAT32",
+            "SPACE_TO_DEPTH_FLOAT32",
+            "LOCAL_RESPONSE_NORMALIZATION_FLOAT32",
+            "SOFTMAX_FLOAT32",
+            "RESHAPE_FLOAT32",
+            "SPLIT_FLOAT32",
+            "FAKE_QUANT_FLOAT32",
+            "ADD_FLOAT32",
+            "FULLY_CONNECTED_FLOAT32",
+            "CAST_FLOAT32",
+            "MUL_FLOAT32",
+            "L2_NORMALIZATION_FLOAT32",
+            "LOGISTIC_FLOAT32",
+            "RELU_FLOAT32",
+            "RELU6_FLOAT32",
+            "RELU1_FLOAT32",
+            "TANH_FLOAT32",
+            "DEQUANTIZE_FLOAT32",
+            "FLOOR_FLOAT32",
+            "GATHER_FLOAT32",
+            "RESIZE_BILINEAR_FLOAT32",
+            "LSH_PROJECTION_FLOAT32",
+            "LSTM_FLOAT32",
+            "SVDF_FLOAT32",
+            "RNN_FLOAT32",
+            "N_GRAM_FLOAT32",
+            "LOOKUP_FLOAT32",
+};
+
+const char* getOperationName(uint32_t opCode) {
+    return kOperationNames[opCode];
+}
+
+uint32_t sizeOfDataType[ANEURALNETWORKS_NUMBER_DATA_TYPES]{
+            2,  // ANEURALNETWORKS_FLOAT16
+            4,  // ANEURALNETWORKS_FLOAT32
+            1,  // ANEURALNETWORKS_INT8
+            1,  // ANEURALNETWORKS_UINT8
+            2,  // ANEURALNETWORKS_INT16
+            2,  // ANEURALNETWORKS_UINT16
+            4,  // ANEURALNETWORKS_INT32
+            4,  // ANEURALNETWORKS_UINT32
+            2,  // ANEURALNETWORKS_TENSOR_FLOAT16
+            4,  // ANEURALNETWORKS_TENSOR_FLOAT32
+            1   // ANEURALNETWORKS_TENSOR_SIMMETRICAL_QUANT8
+};
+
+uint32_t sizeOfData(uint32_t type, const Range<uint32_t>& dimensions) {
+    nnAssert(type < ANEURALNETWORKS_NUMBER_DATA_TYPES);
+
+    uint32_t size = sizeOfDataType[type];
+    for (auto d : dimensions) {
+        size *= d;
+    }
+    return size;
+}
+
+}  // namespace nn
+}  // namespace android
diff --git a/common/include/CpuExecutor.h b/common/include/CpuExecutor.h
new file mode 100644
index 0000000..ecccd7c
--- /dev/null
+++ b/common/include/CpuExecutor.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ML_NN_COMMON_CPU_EXECUTOR_H
+#define ANDROID_ML_NN_COMMON_CPU_EXECUTOR_H
+
+#include "HalAbstraction.h"
+#include "OperationsUtils.h"
+#include "Utils.h"
+
+#include <vector>
+
+namespace android {
+namespace nn {
+
+class IModel;
+
+// Information we maintain about each operand during execution.
+struct RunTimeOperandInfo {
+    // The type and dimensions of the operand.  The dimensions can
+    // change at runtime.  We include the type because it's useful
+    // to pass together with the dimension to the functions implementing
+    // the operators.
+    Shape shape;
+    // Where the operand's data is stored.  Check the corresponding
+    // location information in the model to figure out if this points
+    // to memory we have allocated for an temporary operand.
+    void* buffer;
+    // The length of the buffer.
+    uint32_t length;
+    // Keeps track of how many operations have yet to make use
+    // of this temporary variable.  When the count is decremented to 0,
+    // we free the buffer.  For non-temporary variables, this count is
+    // always 0.
+    uint32_t numberOfUsesLeft;
+};
+
+// This class is used to execute a model on the CPU.
+class CpuExecutor {
+public:
+    // The model must outlive the executor.  We prevent it from being modified
+    // while this is executing.
+    CpuExecutor(const IModel* model, const std::vector<InputOutputInfo>& modelInputs,
+                const std::vector<InputOutputInfo>& modelOutputs);
+    // Executes the model. The results will be stored at the locations
+    // specified in the constructor.
+    int run();
+
+private:
+    // Runs one operation of the graph.
+    int executeOperation(const OperationEntry& entry);
+    // Decrement the usage count for the operands listed.  Frees the memory
+    // allocated for any temporary variable with a count of zero.
+    void freeNoLongerUsedOperands(const Range<uint32_t>& inputs);
+
+    // The operand is a model input or output.  Override the information that
+    // came with the model with the one passed by the calling program.
+    void overrideOperand(uint32_t operandIndex, const InputOutputInfo& info);
+
+    // The model that we'll execute.
+    const IModel* mModel;
+    // We're copying the list of all the dimensions from the model, as
+    // these may be modified when we run the operatins.  Since we're
+    // making a full copy, the indexes used in the operand description
+    // stay valid.
+    std::vector<uint32_t> mDimensions;
+    // Runtime information about all the operands.
+    std::vector<RunTimeOperandInfo> mOperands;
+};
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_ML_NN_COMMON_CPU_EXECUTOR_H
diff --git a/common/include/HalAbstraction.h b/common/include/HalAbstraction.h
new file mode 100644
index 0000000..9bf5a6c
--- /dev/null
+++ b/common/include/HalAbstraction.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ML_NN_COMMON_HAL_ABSTRACTION_H
+#define ANDROID_ML_NN_COMMON_HAL_ABSTRACTION_H
+
+#include <vector>
+
+// This class is used to abstract the HAL interface that will be created
+// HIDL gen from the HIDL files.  We may not need this long term, although
+// it is useful for running on a desktop without the HIDL compiler.
+
+namespace android {
+namespace nn {
+
+// The types the operands can take.  These must be the same value as the NN API>
+// TODO Use a single file for both.
+enum class DataType {
+    FLOAT16 = 0,
+    FLOAT32 = 1,
+    INT8 = 2,
+    UINT8 = 3,
+    INT16 = 4,
+    UINT16 = 5,
+    INT32 = 6,
+    UINT32 = 7,
+    TENSOR_FLOAT16 = 8,
+    TENSOR_FLOAT32 = 9,
+    TENSOR_SIMMETRICAL_QUANT8 = 10,
+
+    NUM_DATA_TYPES = 11
+};
+
+// TODO There's currently a 1:1 mapping with the NN API constants.
+// This will no longer be the case once an op supports more than one type.
+// We'll need to add a conversion when finalizing the model.
+enum class OperatorType {
+    AVERAGE_POOL_FLOAT32 = 0,
+    CONCATENATION_FLOAT32 = 1,
+    CONV_FLOAT32 = 2,
+    DEPTHWISE_CONV_FLOAT32 = 3,
+    MAX_POOL_FLOAT32 = 4,
+    L2_POOL_FLOAT32 = 5,
+    DEPTH_TO_SPACE_FLOAT32 = 6,
+    SPACE_TO_DEPTH_FLOAT32 = 7,
+    LOCAL_RESPONSE_NORMALIZATION_FLOAT32 = 8,
+    SOFTMAX_FLOAT32 = 9,
+    RESHAPE_FLOAT32 = 10,
+    SPLIT_FLOAT32 = 11,
+    FAKE_QUANT_FLOAT32 = 12,
+    ADD_FLOAT32 = 13,
+    FULLY_CONNECTED_FLOAT32 = 14,
+    CAST_FLOAT32 = 15,
+    MUL_FLOAT32 = 16,
+    L2_NORMALIZATION_FLOAT32 = 17,
+    LOGISTIC_FLOAT32 = 18,
+    RELU_FLOAT32 = 19,
+    RELU6_FLOAT32 = 20,
+    RELU1_FLOAT32 = 21,
+    TANH_FLOAT32 = 22,
+    DEQUANTIZE_FLOAT32 = 23,
+    FLOOR_FLOAT32 = 24,
+    GATHER_FLOAT32 = 25,
+    RESIZE_BILINEAR_FLOAT32 = 26,
+    LSH_PROJECTION_FLOAT32 = 27,
+    LSTM_FLOAT32 = 28,
+    SVDF_FLOAT32 = 29,
+    RNN_FLOAT32 = 30,
+    N_GRAM_FLOAT32 = 31,
+    LOOKUP_FLOAT32 = 32,
+
+    NUM_OPERATOR_TYPES = 33
+};
+
+// Status of a driver.
+enum Status { AVAILABLE, BUSY, OFFLINE, UNKNOWN };
+
+// Used by a driver to report its performance characteristics.
+// TODO revisit the data types and scales.
+struct PerformanceInfo {
+    float execTime;    // in nanoseconds
+    float powerUsage;  // in picoJoules
+};
+
+// Serialized representation of the model.
+struct SerializedModel {
+    std::vector<uint8_t> memory;
+};
+
+// The capabilities of a driver.
+struct Capabilities {
+    bool supportedOperatorTypes[static_cast<size_t>(OperatorType::NUM_OPERATOR_TYPES)];
+    // TODO Do the same for baseline model IDs
+    bool cachesCompilation;
+    // TODO revisit the data types and scales.
+    float bootupTime;  // in nanoseconds
+    PerformanceInfo float16Performance;
+    PerformanceInfo float32Performance;
+    PerformanceInfo quantized8Performance;
+};
+
+// Informaton about one input or output operand of a model.
+struct InputOutputInfo {
+    void* buffer;
+    uint32_t length;  // In bytes.
+    // If true, the calling program has provided different dimensions for the
+    // operand than was specified in the model.
+    bool dimensionChanged;
+    // The dimensions to use if the dimensions have been changed.
+    std::vector<uint32_t> dimensions;
+};
+
+// See the HAL files for documentation on these interfaces.
+class IEvent {
+public:
+    virtual ~IEvent(){}
+    virtual uint32_t wait() = 0;
+};
+
+class IRequest {
+public:
+    virtual ~IRequest(){}
+    virtual int execute(const std::vector<InputOutputInfo>& inputs,
+                        const std::vector<InputOutputInfo>& outputs, IEvent** event) = 0;
+    virtual void releaseTempMemory() = 0;
+};
+
+class IDevice {
+public:
+    virtual ~IDevice(){}
+    virtual void initialize(Capabilities* capabilities) = 0;
+    virtual void getSupportedSubgraph(void* graph, std::vector<bool>& canDo) = 0;
+    virtual int prepareRequest(const SerializedModel* model, IRequest** request) = 0;
+    virtual Status getStatus() = 0;
+};
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_ML_NN_COMMON_HAL_ABSTRACTION_H
diff --git a/common/include/HalModel.h b/common/include/HalModel.h
new file mode 100644
index 0000000..40247e1
--- /dev/null
+++ b/common/include/HalModel.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ML_NN_COMMON_HAL_MODEL_H
+#define ANDROID_ML_NN_COMMON_HAL_MODEL_H
+
+// This file contains the data structures that used to access the
+
+//namespace android {
+//namespace nn {
+
+#include <cstdint>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// The location will be specified at runtime. It's either a temporary
+// variable, an input, or an output.
+const uint32_t LOCATION_AT_RUN_TIME = 0xFFFFFFFF;
+// The operand's value is in the same memory pool as the model.
+const uint32_t LOCATION_SAME_BLOCK = 0xFFFFFFFE;
+
+// Used to represent a variable length array.
+struct ArrayInfo {
+    // The number of elements of the array.
+    uint32_t count;
+    // The offset in whichevere data structure to find the first
+    // element of the array.  The unit type of the offset depends
+    // on the data structure it is indexing.
+    uint32_t offset;
+};
+
+// A serialized model starts with this block of memory.
+// TODO Look into alignment or padding issues.
+struct ModelHeader {
+    // Size and location of the operation table, an array of OperationEntry.
+    // The offset is the distance in bytes from the start of the header.
+    ArrayInfo operations;
+    // Size and location of the operand table, an array of OperandEntry.
+    // The offset is the distance in bytes from the start of the header.
+    ArrayInfo operands;
+    // Size and location of the table of dimensions, an array of uint32_t.
+    // The offset is the distance in bytes from the start of the header.
+    ArrayInfo dimensions;
+    // Size and location of the table of operand indexes, an array of uint32_t.
+    // The offset is the distance in bytes from the start of the header.
+    ArrayInfo operandIndexes;
+    // Size and location of the memory block containing all the fixed
+    // operand values.  The element type is uint8_t.
+    // The offset is the distance in bytes from the start of the header.
+    ArrayInfo operandValues;
+
+    // The list of operand indexes for the inputs of the model.
+    // The offset is an index in the operandIndexes table.
+    ArrayInfo modelInputs;
+    // The list of operand indexes for the outputs of the model.
+    // The offset is an index in the operandIndexes table.
+    ArrayInfo modelOutputs;
+};
+
+// Describes one operation of the graph.
+struct OperationEntry {
+    // The type of operation.
+    uint32_t opCode;
+    // Describes the table that contains the indexes of the inputs of the
+    // operation. The offset is the index in the operandIndexes table.
+    ArrayInfo inputs;
+    // Describes the table that contains the indexes of the outputs of the
+    // operation. The offset is the index in the operandIndexes table.
+    ArrayInfo outputs;
+};
+
+// Describes the location of a data object.
+struct DataLocation {
+    // The index of the memory pool where this location is found.
+    // Two special values can also be used.  See the LOCATION_* constants above.
+    uint32_t pool;
+    // Offset in bytes from the start of the pool.
+    uint32_t offset;
+};
+
+// Describes one operand of the graph.
+struct OperandEntry {
+    uint32_t type;
+    // The number of operations that uses this operand as input.
+    uint32_t numberOfConsumers;
+    // TODO handle quantization params.
+
+    // The following three fields maybe superseded at runtime.
+
+    // Dimensions of the operand.  The offset is an index in the dimensions table.
+    ArrayInfo dimensions;
+    // Where to find the data for this operand.
+    DataLocation location;
+    // The length of the data, in bytes.
+    uint32_t length;
+};
+
+__END_DECLS
+
+//}  // namespace nn
+//}  // namespace android
+
+#endif  // ANDROID_ML_NN_COMMON_HAL_MODEL_H
diff --git a/common/include/Model.h b/common/include/Model.h
new file mode 100644
index 0000000..0efc967
--- /dev/null
+++ b/common/include/Model.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Interface used by the CpuExecutor to communicate with the two model
+// implementations.
+
+#ifndef ANDROID_ML_NN_COMMON_MODEL_BUILDER_H
+#define ANDROID_ML_NN_COMMON_MODEL_BUILDER_H
+
+#include "Utils.h"
+
+namespace android {
+namespace nn {
+
+class IModel {
+public:
+    virtual ~IModel() {}
+    virtual Range<OperationEntry> getOperations() const = 0;
+    virtual Range<OperandEntry> getOperands() const = 0;
+    virtual Range<uint32_t> getOperandIndexes(const ArrayInfo& info) const = 0;
+    virtual void copyDimensionStorage(std::vector<uint32_t>* dimensions) const = 0;
+    virtual uint32_t getInputOperandIndex(uint32_t listIndex) const = 0;
+    virtual uint32_t getOutputOperandIndex(uint32_t listIndex) const = 0;
+    virtual const void* getDataPointer(uint32_t offset) const = 0;
+};
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_ML_NN_COMMON_MODEL_BUILDER_H
diff --git a/common/include/Operations.h b/common/include/Operations.h
new file mode 100644
index 0000000..56d1c92
--- /dev/null
+++ b/common/include/Operations.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ML_NN_COMMON_OPERATIONS_H
+#define ANDROID_ML_NN_COMMON_OPERATIONS_H
+
+#include <stddef.h>
+
+namespace android {
+namespace nn {
+
+struct Shape;
+
+bool addTensorsFloat32(const float* in1, const float* in2, float* out, const Shape& shape);
+bool addTensorsFloat32Prepare(const Shape& in1, const Shape& in2, Shape* out1);
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_ML_NN_COMMON_OPERATIONS_H
diff --git a/common/include/OperationsUtils.h b/common/include/OperationsUtils.h
new file mode 100644
index 0000000..ec45912
--- /dev/null
+++ b/common/include/OperationsUtils.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ML_NN_COMMON_OPERATIONS_UTILS_H
+#define ANDROID_ML_NN_COMMON_OPERATIONS_UTILS_H
+
+#include <cstdint>
+
+namespace android {
+namespace nn {
+
+// The type and dimensions of an operand.
+struct Shape {
+    uint32_t type;
+    uint32_t numberOfDimensions;
+    uint32_t* dimensions;
+};
+
+// Verifies that the two shapes are the same.
+bool SameShape(const Shape& in1, const Shape& in2);
+
+// Sets out to the same shape as in.
+bool SetShape(const Shape& in, const Shape* out);
+
+// Return the total number of elements, i.e. all the dimensions multiplied
+// together. For a scalar, returns one.
+uint32_t getNumberOfElements(const Shape& shape);
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_ML_NN_COMMON_OPERATIONS_UTILS_H
diff --git a/common/include/Utils.h b/common/include/Utils.h
new file mode 100644
index 0000000..e3619e1
--- /dev/null
+++ b/common/include/Utils.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ML_NN_COMMON_UTILS_H
+#define ANDROID_ML_NN_COMMON_UTILS_H
+
+#include "HalModel.h"
+
+#include <stdio.h>
+#include <vector>
+
+namespace android {
+namespace nn {
+
+// TODO Replace with the real Android logging macros.
+#define ALOGE(format, ...) printf(LOG_TAG ": ERROR " format "\n", ##__VA_ARGS__)
+#define ALOGI(format, ...) printf(LOG_TAG ": " format "\n", ##__VA_ARGS__)
+
+// Assert macro, as Android does not generally support assert.
+#define nnAssert(v)                                                                       \
+    do {                                                                                  \
+        if (!(v)) {                                                                       \
+            fprintf(stderr, "nnAssert failed at %s:%d - '%s'\n", __FILE__, __LINE__, #v); \
+            abort();                                                                      \
+        }                                                                                 \
+    } while (0)
+
+// Represent a list of items.  Handy to iterate over lists and sublists.
+template <typename T>
+class Range {
+public:
+    // The default constructor should only be used when followed by a call
+    // to setFromBuffer.
+    Range() {}
+    // Range over all the elements of the vector.
+    Range(const std::vector<T>& data) {
+        mCount = static_cast<uint32_t>(data.size());
+        mBegin = data.data();
+    }
+    // Range over the sublist of elements of the vector, as specified by info.
+    Range(const std::vector<T>& data, const ArrayInfo& info) {
+        mCount = info.count;
+        mBegin = data.data() + info.offset;
+    }
+    // Range over the sublist of the range, as specified by info.
+    Range(const Range<T>& data, const ArrayInfo& info) {
+        mCount = info.count;
+        mBegin = data.begin() + info.offset;
+    }
+    // Range of the specified number of elements, starting at the specified value.
+    Range(uint32_t count, T* start) {
+        mCount = count;
+        mBegin = start;
+    }
+
+    // Range over consecutive elements starting at buffer + info.offset.
+    void setFromBuffer(const ArrayInfo& info, const uint8_t* buffer) {
+        mCount = info.count;
+        mBegin = reinterpret_cast<const T*>(buffer + info.offset);
+    }
+
+    // These two methods enable the use of for(x:Range(..)).
+    const T* begin() const { return mBegin; }
+    const T* end() const { return mBegin + mCount; }
+
+    // Returns the element at the specifed index.
+    T operator[](uint32_t index) const {
+        nnAssert(index < mCount);
+        return mBegin[index];
+    }
+    // All our ranges are read-only.  If we need to write, use this:
+    // uint32_t& operator[] (uint32_t index) {
+    //    nnAssert(index < mCount);
+    //    return mBegin[index];
+    // }
+
+    uint32_t count() const { return mCount; }
+
+private:
+    const T* mBegin = nullptr;  // The start of the range.
+    uint32_t mCount = 0;        // The number of elements in the range.
+};
+
+// Returns the the amount of space needed to store a tensor of the specified
+// dimensions and type.
+uint32_t sizeOfData(uint32_t type, const Range<uint32_t>& dimensions);
+
+// Returns the name of the operation in ASCII.
+const char* getOperationName(uint32_t opCode);
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_ML_NN_COMMON_UTILS_H