2 * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.samsung.android.aittnative;
18 import android.util.Log;
19 import android.util.Pair;
21 import java.util.ArrayList;
22 import java.util.HashMap;
26 * Jni Interface class as intermediate layer for android aitt and other transport modules to interact with JNI module.
28 public class JniInterface {
29 private static final String TAG = "JniInterface";
30 private final Map<String, ArrayList<JniMessageCallback>> subscribeCallbacks = new HashMap<>();
31 private final Map<String, Pair<Integer, JniDiscoveryCallback>> discoveryCallbacks = new HashMap<>();
32 private JniConnectionCallback jniConnectionCallback;
33 private long instance = 0;
36 Load aitt-native library
40 System.loadLibrary("aitt-native");
41 } catch (UnsatisfiedLinkError e) {
42 // only ignore exception in non-android env
43 if ("Dalvik".equals(System.getProperty("java.vm.name"))) throw e;
48 * JNI callback interface to send data from JNI layer to Java layer(aitt or transport module)
50 public interface JniMessageCallback {
51 void onDataReceived(String topic, byte[] data);
55 * JNI callback interface to send connection callback status to aitt layer
57 public interface JniConnectionCallback {
58 void onConnectionStatusReceived(int status);
62 * JNI callback interface to receive discovery messages
64 public interface JniDiscoveryCallback {
65 void onDiscoveryMessageReceived(String status, byte[] data);
69 * JNI interface API to initialize JNI module
70 * @param id unique mqtt id
71 * @param ip self IP address of device
72 * @param clearSession to clear current session if client disconnects
73 * @return returns the JNI instance object in long
75 public long init(String id, String ip, boolean clearSession) {
76 instance = initJNI(id, ip, clearSession);
81 * JNI Interface API to connect to MQTT broker
82 * @param brokerIp mqtt broker ip address
83 * @param port mqtt broker port number
85 public void connect(String brokerIp, int port) {
86 connectJNI(instance, brokerIp, port);
90 * JNI Interface API to subscribe to a topic
91 * @param topic String to which applications can subscribe, to receive data
92 * @param protocol Protocol supported by application, invoking subscribe
93 * @param qos QoS at which the message should be delivered
94 * @return returns the subscribe instance in long
96 public long subscribe(final String topic, JniMessageCallback callback, int protocol, int qos) {
97 addCallBackToSubscribeMap(topic, callback);
98 return subscribeJNI(instance, topic, protocol, qos);
102 * JNI Interface API to disconnect from broker
104 public void disconnect() {
105 synchronized (this) {
106 subscribeCallbacks.clear();
107 discoveryCallbacks.clear();
108 jniConnectionCallback = null;
110 disconnectJNI(instance);
114 * JNI Interface API to publish data to specified topic
115 * @param topic String to which message needs to be published
116 * @param data Byte message to be published
117 * @param dataLen Size/length of the message to be published
118 * @param protocol Protocol to be used to publish message
119 * @param qos QoS at which the message should be delivered
120 * @param retain Boolean to decide whether or not the message should be retained by the broker
122 public void publish(final String topic, final byte[] data, long dataLen, int protocol, int qos, boolean retain) {
123 publishJNI(instance, topic, data, dataLen, protocol, qos, retain);
127 * JNI Interface API to unsubscribe the given topic
128 * @param aittSubId Subscribe ID of the topics to be unsubscribed
130 public void unsubscribe(String topic, final long aittSubId) {
131 synchronized (this) {
132 subscribeCallbacks.remove(topic);
134 unsubscribeJNI(instance, aittSubId);
138 * JNI Interface API to set connection callback instance
139 * @param cb callback instance of JniConnectionCallback interface
141 public void setConnectionCallback(JniConnectionCallback cb) {
142 jniConnectionCallback = cb;
143 setConnectionCallbackJNI(instance);
147 * JNI Interface API to set discovery callback
148 * @param topic String for which discovery information is required
149 * @param callback callback instance of JniDiscoveryCallback interface
151 public void setDiscoveryCallback(String topic, JniDiscoveryCallback callback) {
152 int cb = setDiscoveryCallbackJNI(instance, topic);
153 synchronized (this) {
154 discoveryCallbacks.put(topic, new Pair<>(cb, callback));
159 * JNI Interface API to remove discovery callback
160 * @param topic String for which discovery information is not required
162 public void removeDiscoveryCallback(String topic) {
163 synchronized (this) {
164 Pair<Integer, JniDiscoveryCallback> pair = discoveryCallbacks.get(topic);
166 removeDiscoveryCallbackJNI(instance, pair.first);
168 discoveryCallbacks.remove(topic);
173 * JNI Interface API to update discovery message
174 * @param topic String for which discovery information is to be updated
175 * @param discoveryMessage ByteArray containing discovery information
177 public void updateDiscoveryMessage(String topic, byte[] discoveryMessage) {
178 updateDiscoveryMessageJNI(instance, topic, discoveryMessage, discoveryMessage.length);
182 * messageCallback API to receive data from JNI layer to JNI interface layer
183 * @param topic Topic to which data is received
184 * @param payload Data that is sent from JNI to JNI interface layer
186 void messageCallback(String topic, byte[] payload) {
188 synchronized (this) {
189 ArrayList<JniMessageCallback> cbList = subscribeCallbacks.get(topic);
191 if (cbList != null) {
192 for (JniMessageCallback cb : cbList) {
193 cb.onDataReceived(topic, payload);
197 } catch (Exception e) {
198 Log.e(TAG, "Error during messageReceived", e);
203 * connectionStatusCallback API to receive connection status from JNI to JNI interface layer
204 * @param status status of the device connection with mqtt broker
206 void connectionStatusCallback(int status) {
207 if (jniConnectionCallback != null) {
208 jniConnectionCallback.onConnectionStatusReceived(status);
212 void discoveryMessageCallback(String topic, String status, byte[] message) {
213 synchronized (this) {
214 Pair<Integer, JniDiscoveryCallback> pair = discoveryCallbacks.get(topic);
216 pair.second.onDiscoveryMessageReceived(status, message);
222 * Method to map JNI callback instance to topic
224 * @param topic String to which application can subscribe
225 * @param callback JniInterface callback instance created during JNI subscribe call
227 private void addCallBackToSubscribeMap(String topic, JniMessageCallback callback) {
228 synchronized (this) {
230 ArrayList<JniMessageCallback> cbList = subscribeCallbacks.get(topic);
232 if (cbList != null) {
233 // check whether the list already contains same callback
234 if (!cbList.contains(callback)) {
235 cbList.add(callback);
238 cbList = new ArrayList<>();
239 cbList.add(callback);
240 subscribeCallbacks.put(topic, cbList);
242 } catch (Exception e) {
243 Log.e(TAG, "Error during JNI callback add", e);
249 /* Native API to initialize JNI */
250 private native long initJNI(String id, String ip, boolean clearSession);
252 /* Native API for connecting to broker */
253 private native void connectJNI(long instance, final String host, int port);
255 /* Native API for disconnecting from broker */
256 private native void disconnectJNI(long instance);
258 /* Native API for setting connection callback */
259 private native void setConnectionCallbackJNI(long instance);
261 /* Native API for setting discovery callback */
262 private native int setDiscoveryCallbackJNI(long instance, final String topic);
264 /* Native API for removing discovery callback */
265 private native void removeDiscoveryCallbackJNI(long instance, int cbHandle);
267 /* Native API for updating discovery message */
268 private native void updateDiscoveryMessageJNI(long instance, final String topic, final byte[] data, long dataLen);
270 /* Native API for publishing to a topic */
271 private native void publishJNI(long instance, final String topic, final byte[] data, long dataLen, int protocol, int qos, boolean retain);
273 /* Native API for subscribing to a topic */
274 private native long subscribeJNI(long instance, final String topic, int protocol, int qos);
276 /* Native API for unsubscribing a topic */
277 private native void unsubscribeJNI(long instance, final long aittSubId);