1/*
2 * Copyright (C) 2011 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
18package android.filterfw.core;
19
20import android.filterfw.core.Frame;
21import android.filterfw.core.Program;
22
23/**
24 * @hide
25 */
26public class NativeProgram extends Program {
27
28    private int nativeProgramId;
29    private boolean mHasInitFunction     = false;
30    private boolean mHasTeardownFunction = false;
31    private boolean mHasSetValueFunction = false;
32    private boolean mHasGetValueFunction = false;
33    private boolean mHasResetFunction = false;
34    private boolean mTornDown = false;
35
36    public NativeProgram(String nativeLibName, String nativeFunctionPrefix) {
37        // Allocate the native instance
38        allocate();
39
40        // Open the native library
41        String fullLibName = "lib" + nativeLibName + ".so";
42        if (!openNativeLibrary(fullLibName)) {
43            throw new RuntimeException("Could not find native library named '" + fullLibName + "' " +
44                                       "required for native program!");
45        }
46
47        // Bind the native functions
48        String processFuncName = nativeFunctionPrefix + "_process";
49        if (!bindProcessFunction(processFuncName)) {
50            throw new RuntimeException("Could not find native program function name " +
51                                       processFuncName + " in library " + fullLibName + "! " +
52                                       "This function is required!");
53        }
54
55        String initFuncName = nativeFunctionPrefix + "_init";
56        mHasInitFunction = bindInitFunction(initFuncName);
57
58        String teardownFuncName = nativeFunctionPrefix + "_teardown";
59        mHasTeardownFunction = bindTeardownFunction(teardownFuncName);
60
61        String setValueFuncName = nativeFunctionPrefix + "_setvalue";
62        mHasSetValueFunction = bindSetValueFunction(setValueFuncName);
63
64        String getValueFuncName = nativeFunctionPrefix + "_getvalue";
65        mHasGetValueFunction = bindGetValueFunction(getValueFuncName);
66
67        String resetFuncName = nativeFunctionPrefix + "_reset";
68        mHasResetFunction = bindResetFunction(resetFuncName);
69
70        // Initialize the native code
71        if (mHasInitFunction && !callNativeInit()) {
72            throw new RuntimeException("Could not initialize NativeProgram!");
73        }
74    }
75
76    public void tearDown() {
77        if (mTornDown) return;
78        if (mHasTeardownFunction && !callNativeTeardown()) {
79            throw new RuntimeException("Could not tear down NativeProgram!");
80        }
81        deallocate();
82        mTornDown = true;
83    }
84
85    @Override
86    public void reset() {
87        if (mHasResetFunction && !callNativeReset()) {
88            throw new RuntimeException("Could not reset NativeProgram!");
89        }
90    }
91
92    @Override
93    protected void finalize() throws Throwable {
94        tearDown();
95    }
96
97    @Override
98    public void process(Frame[] inputs, Frame output) {
99        if (mTornDown) {
100            throw new RuntimeException("NativeProgram already torn down!");
101        }
102        NativeFrame[] nativeInputs = new NativeFrame[inputs.length];
103        for (int i = 0; i < inputs.length; ++i) {
104            if (inputs[i] == null || inputs[i] instanceof NativeFrame) {
105                nativeInputs[i] = (NativeFrame)inputs[i];
106            } else {
107                throw new RuntimeException("NativeProgram got non-native frame as input "+ i +"!");
108            }
109        }
110
111        // Get the native output frame
112        NativeFrame nativeOutput = null;
113        if (output == null || output instanceof NativeFrame) {
114            nativeOutput = (NativeFrame)output;
115        } else {
116            throw new RuntimeException("NativeProgram got non-native output frame!");
117        }
118
119        // Process!
120        if (!callNativeProcess(nativeInputs, nativeOutput)) {
121            throw new RuntimeException("Calling native process() caused error!");
122        }
123    }
124
125    @Override
126    public void setHostValue(String variableName, Object value) {
127        if (mTornDown) {
128            throw new RuntimeException("NativeProgram already torn down!");
129        }
130        if (!mHasSetValueFunction) {
131            throw new RuntimeException("Attempting to set native variable, but native code does not " +
132                                       "define native setvalue function!");
133        }
134        if (!callNativeSetValue(variableName, value.toString())) {
135            throw new RuntimeException("Error setting native value for variable '" + variableName + "'!");
136        }
137    }
138
139    @Override
140    public Object getHostValue(String variableName) {
141        if (mTornDown) {
142            throw new RuntimeException("NativeProgram already torn down!");
143        }
144        if (!mHasGetValueFunction) {
145            throw new RuntimeException("Attempting to get native variable, but native code does not " +
146                                       "define native getvalue function!");
147        }
148        return callNativeGetValue(variableName);
149    }
150
151    static {
152        System.loadLibrary("filterfw");
153    }
154
155    private native boolean allocate();
156
157    private native boolean deallocate();
158
159    private native boolean nativeInit();
160
161    private native boolean openNativeLibrary(String libName);
162
163    private native boolean bindInitFunction(String funcName);
164    private native boolean bindSetValueFunction(String funcName);
165    private native boolean bindGetValueFunction(String funcName);
166    private native boolean bindProcessFunction(String funcName);
167    private native boolean bindResetFunction(String funcName);
168    private native boolean bindTeardownFunction(String funcName);
169
170    private native boolean callNativeInit();
171    private native boolean callNativeSetValue(String key, String value);
172    private native String  callNativeGetValue(String key);
173    private native boolean callNativeProcess(NativeFrame[] inputs, NativeFrame output);
174    private native boolean callNativeReset();
175    private native boolean callNativeTeardown();
176}
177