/*
* Copyright (c) 2017-2019 Cisco and/or its affiliates.
* 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.
*/
/**
* \file interfaces/android_utility/android_utility.c
* \brief Implementation of Android utility.
*/
#include <assert.h>
#include <hicn/facemgr.h>
#include <hicn/ctrl/face.h>
#include <hicn/util/log.h>
#include "../../common.h"
#include "../../facelet.h"
#include "../../interface.h"
#include <hicn/android_utility/android_utility.h>
#define FACEMGR_ANDROID_UTILITY_CLASS "com/cisco/hicn/forwarder/supportlibrary/AndroidUtility"
#define AU_INTERFACE_TYPE_UNDEFINED 0
#define AU_INTERFACE_TYPE_WIRED 1
#define AU_INTERFACE_TYPE_WIFI 2
#define AU_INTERFACE_TYPE_CELLULAR 3
#define AU_INTERFACE_TYPE_LOOPBACK 4 /* not supported yet */
#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration."
typedef struct {
android_utility_cfg_t cfg;
} au_data_t;
int au_initialize(interface_t * interface, void * cfg)
{
au_data_t * data = malloc(sizeof(au_data_t));
if (!data)
return -1;
interface->data = data;
if (!cfg)
goto ERR_CFG;
data->cfg = * (android_utility_cfg_t *) cfg;
if (!data->cfg.jvm)
goto ERR_CFG;
return 0;
ERR_CFG:
fprintf(stderr, ERR_STR_JAVA);
return -1;
}
int au_finalize(interface_t * interface)
{
/* Nothing to do */
return 0;
}
int au_on_event(interface_t * interface, const facelet_t * facelet)
{
/*
* This function is responsible to annotate every face we receive with the
* correct interface type, based on the value returned by the Android
* utility shipped with the Android forwarder.
*/
DEBUG("Android utility received request");
au_data_t * data = (au_data_t*)interface->data;
netdevice_t netdevice = NETDEVICE_EMPTY;
int rc = facelet_get_netdevice(facelet, &netdevice);
if (rc < 0)
return -1;
DEBUG("[au_on_event] netdevice=%s", netdevice.name);
JNIEnv *env;
JavaVM *jvm = data->cfg.jvm;
(*jvm)->AttachCurrentThread(jvm, &env, NULL);
jclass cls = (*env)->FindClass(env, FACEMGR_ANDROID_UTILITY_CLASS);
jmethodID getNetworkType = (*env)->GetStaticMethodID(env, cls,
"getNetworkType", "(Ljava/lang/String;)I");
jint interface_type = (*env)->CallStaticIntMethod(env, cls, getNetworkType,
(*env)->NewStringUTF(env, netdevice.name));
DEBUG("Processing results for interface %s", netdevice.name);
netdevice_type_t netdevice_type = AU_INTERFACE_TYPE_UNDEFINED;
switch(interface_type) {
case AU_INTERFACE_TYPE_UNDEFINED:
break;
case AU_INTERFACE_TYPE_WIRED:
netdevice_type = NETDEVICE_TYPE_WIRED;
break;
case AU_INTERFACE_TYPE_WIFI:
netdevice_type = NETDEVICE_TYPE_WIFI;
break;
case AU_INTERFACE_TYPE_CELLULAR:
netdevice_type = NETDEVICE_TYPE_CELLULAR;
break;
case AU_INTERFACE_TYPE_LOOPBACK:
netdevice_type = NETDEVICE_TYPE_LOOPBACK;
break;
default:
return -1;
}
facelet_t * facelet_new = facelet_create();
facelet_set_netdevice(facelet_new, netdevice);
facelet_set_status(facelet_new, FACELET_STATUS_CLEAN);
facelet_set_netdevice_type(facelet_new, netdevice_type);
DEBUG("sending AU udpate");
facelet_set_event(facelet_new, FACELET_EVENT_UPDATE);
interface_raise_event(interface, facelet_new);
return 0;
}
const interface_ops_t android_utility_ops = {
.type = "android_utility",
.initialize = au_initialize,
.finalize = au_finalize,
.callback = NULL,
.on_event = au_on_event,
};