/*
 * Copyright 2016, 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 "wifinan"

#include "jni.h"
#include "JniConstants.h"
#include <ScopedUtfChars.h>
#include <ScopedBytes.h>
#include <utils/misc.h>
#include <utils/Log.h>
#include <utils/String16.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <linux/if.h>
#include "wifi.h"
#include "wifi_hal.h"
#include "jni_helper.h"

namespace android {

static jclass mCls;                             /* saved WifiNanNative object */
static JavaVM *mVM = NULL;                      /* saved JVM pointer */

wifi_handle getWifiHandle(JNIHelper &helper, jclass cls);
wifi_interface_handle getIfaceHandle(JNIHelper &helper, jclass cls, jint index);

extern wifi_hal_fn hal_fn;

// Start NAN functions

static void OnNanNotifyResponse(transaction_id id, NanResponseMsg* msg) {
  ALOGD(
      "OnNanNotifyResponse: transaction_id=%d, status=%d, value=%d, response_type=%d",
      id, msg->status, msg->value, msg->response_type);

  JNIHelper helper(mVM);
  switch (msg->response_type) {
    case NAN_RESPONSE_PUBLISH:
      helper.reportEvent(mCls, "onNanNotifyResponsePublishSubscribe",
                         "(SIIII)V", (short) id, (int) msg->response_type,
                         (int) msg->status, (int) msg->value,
                         msg->body.publish_response.publish_id);
      break;
    case NAN_RESPONSE_SUBSCRIBE:
      helper.reportEvent(mCls, "onNanNotifyResponsePublishSubscribe",
                         "(SIIII)V", (short) id, (int) msg->response_type,
                         (int) msg->status, (int) msg->value,
                         msg->body.subscribe_response.subscribe_id);
      break;
    case NAN_GET_CAPABILITIES: {
      JNIObject<jobject> data = helper.createObject(
          "com/android/server/wifi/nan/WifiNanNative$Capabilities");
      if (data == NULL) {
        ALOGE(
            "Error in allocating WifiNanNative.Capabilities OnNanNotifyResponse");
        return;
      }

      helper.setIntField(
          data, "maxConcurrentNanClusters",
          (int) msg->body.nan_capabilities.max_concurrent_nan_clusters);
      helper.setIntField(data, "maxPublishes",
                         (int) msg->body.nan_capabilities.max_publishes);
      helper.setIntField(data, "maxSubscribes",
                         (int) msg->body.nan_capabilities.max_subscribes);
      helper.setIntField(data, "maxServiceNameLen",
                         (int) msg->body.nan_capabilities.max_service_name_len);
      helper.setIntField(data, "maxMatchFilterLen",
                         (int) msg->body.nan_capabilities.max_match_filter_len);
      helper.setIntField(
          data, "maxTotalMatchFilterLen",
          (int) msg->body.nan_capabilities.max_total_match_filter_len);
      helper.setIntField(
          data, "maxServiceSpecificInfoLen",
          (int) msg->body.nan_capabilities.max_service_specific_info_len);
      helper.setIntField(data, "maxVsaDataLen",
                         (int) msg->body.nan_capabilities.max_vsa_data_len);
      helper.setIntField(data, "maxMeshDataLen",
                         (int) msg->body.nan_capabilities.max_mesh_data_len);
      helper.setIntField(data, "maxNdiInterfaces",
                         (int) msg->body.nan_capabilities.max_ndi_interfaces);
      helper.setIntField(data, "maxNdpSessions",
                         (int) msg->body.nan_capabilities.max_ndp_sessions);
      helper.setIntField(data, "maxAppInfoLen",
                         (int) msg->body.nan_capabilities.max_app_info_len);
      helper.setIntField(data, "maxQueuedTransmitMessages",
                         (int) msg->body.nan_capabilities.max_queued_transmit_followup_msgs);

      helper.reportEvent(
          mCls, "onNanNotifyResponseCapabilities",
          "(SIILcom/android/server/wifi/nan/WifiNanNative$Capabilities;)V",
          (short) id, (int) msg->status, (int) msg->value, data.get());
      break;
    }
    default:
      helper.reportEvent(mCls, "onNanNotifyResponse", "(SIII)V", (short) id,
                         (int) msg->response_type, (int) msg->status,
                         (int) msg->value);
      break;
  }
}

static void OnNanEventPublishTerminated(NanPublishTerminatedInd* event) {
    ALOGD("OnNanEventPublishTerminated");

    JNIHelper helper(mVM);
    helper.reportEvent(mCls, "onPublishTerminated", "(II)V",
                       event->publish_id, event->reason);
}

static void OnNanEventMatch(NanMatchInd* event) {
    ALOGD("OnNanEventMatch");

    JNIHelper helper(mVM);

    JNIObject<jbyteArray> macBytes = helper.newByteArray(6);
    helper.setByteArrayRegion(macBytes, 0, 6, (jbyte *) event->addr);

    JNIObject<jbyteArray> ssiBytes = helper.newByteArray(event->service_specific_info_len);
    helper.setByteArrayRegion(ssiBytes, 0, event->service_specific_info_len,
                              (jbyte *) event->service_specific_info);

    JNIObject<jbyteArray> mfBytes = helper.newByteArray(event->sdf_match_filter_len);
    helper.setByteArrayRegion(mfBytes, 0, event->sdf_match_filter_len,
                              (jbyte *) event->sdf_match_filter);

    helper.reportEvent(mCls, "onMatchEvent", "(II[B[BI[BI)V",
                       (int) event->publish_subscribe_id,
                       (int) event->requestor_instance_id,
                       macBytes.get(),
                       ssiBytes.get(), event->service_specific_info_len,
                       mfBytes.get(), event->sdf_match_filter_len);
}

static void OnNanEventMatchExpired(NanMatchExpiredInd* event) {
    ALOGD("OnNanEventMatchExpired");
}

static void OnNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) {
    ALOGD("OnNanEventSubscribeTerminated");

    JNIHelper helper(mVM);
    helper.reportEvent(mCls, "onSubscribeTerminated", "(II)V",
                       event->subscribe_id, event->reason);
}

static void OnNanEventFollowup(NanFollowupInd* event) {
    ALOGD("OnNanEventFollowup");

    JNIHelper helper(mVM);

    JNIObject<jbyteArray> macBytes = helper.newByteArray(6);
    helper.setByteArrayRegion(macBytes, 0, 6, (jbyte *) event->addr);

    JNIObject<jbyteArray> msgBytes = helper.newByteArray(event->service_specific_info_len);
    helper.setByteArrayRegion(msgBytes, 0, event->service_specific_info_len, (jbyte *) event->service_specific_info);

    helper.reportEvent(mCls, "onFollowupEvent", "(II[B[BI)V",
                       (int) event->publish_subscribe_id,
                       (int) event->requestor_instance_id,
                       macBytes.get(),
                       msgBytes.get(),
                       (int) event->service_specific_info_len);
}

static void OnNanEventDiscEngEvent(NanDiscEngEventInd* event) {
    ALOGD("OnNanEventDiscEngEvent called: event_type=%d", event->event_type);

    JNIHelper helper(mVM);

    JNIObject<jbyteArray> macBytes = helper.newByteArray(6);
    if (event->event_type == NAN_EVENT_ID_DISC_MAC_ADDR) {
        helper.setByteArrayRegion(macBytes, 0, 6, (jbyte *) event->data.mac_addr.addr);
    } else {
        helper.setByteArrayRegion(macBytes, 0, 6, (jbyte *) event->data.cluster.addr);
    }

    helper.reportEvent(mCls, "onDiscoveryEngineEvent", "(I[B)V",
                       (int) event->event_type, macBytes.get());
}

static void OnNanEventDisabled(NanDisabledInd* event) {
    ALOGD("OnNanEventDisabled called: reason=%d", event->reason);

    JNIHelper helper(mVM);

    helper.reportEvent(mCls, "onDisabledEvent", "(I)V", (int) event->reason);
}

static void OnNanEventTca(NanTCAInd* event) {
    ALOGD("OnNanEventTca");
}

static void OnNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) {
    ALOGD("OnNanEventSdfPayload");
}

static void OnNanEventDataRequest(NanDataPathRequestInd* event) {
  ALOGD("OnNanEventDataRequest");
}

static void OnNanEventDataConfirm(NanDataPathConfirmInd* event) {
  ALOGD("OnNanEventDataConfirm");
}

static void OnNanEventDataEnd(NanDataPathEndInd* event) {
  ALOGD("OnNanEventDataEnd");
}

static void OnNanEventTransmitFollowup(NanTransmitFollowupInd* event) {
  ALOGD("OnNanEventTransmitFollowup: transaction_id=%d, reason=%d", event->id,
        event->reason);

  JNIHelper helper(mVM);

  helper.reportEvent(mCls, "onTransmitFollowupEvent", "(SI)V",
                     (short) event->id, (int) event->reason);
}

static jint android_net_wifi_nan_register_handler(JNIEnv *env, jclass cls,
                                                  jclass wifi_native_cls,
                                                  jint iface) {
    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

    ALOGD("android_net_wifi_nan_register_handler handle=%p", handle);

    NanCallbackHandler handlers;
    memset(&handlers, 0, sizeof(NanCallbackHandler));
    handlers.NotifyResponse = OnNanNotifyResponse;
    handlers.EventPublishTerminated = OnNanEventPublishTerminated;
    handlers.EventMatch = OnNanEventMatch;
    handlers.EventMatchExpired = OnNanEventMatchExpired;
    handlers.EventSubscribeTerminated = OnNanEventSubscribeTerminated;
    handlers.EventFollowup = OnNanEventFollowup;
    handlers.EventDiscEngEvent = OnNanEventDiscEngEvent;
    handlers.EventDisabled = OnNanEventDisabled;
    handlers.EventTca = OnNanEventTca;
    handlers.EventBeaconSdfPayload = OnNanEventBeaconSdfPayload;
    handlers.EventDataRequest = OnNanEventDataRequest;
    handlers.EventDataConfirm = OnNanEventDataConfirm;
    handlers.EventDataEnd = OnNanEventDataEnd;
    handlers.EventTransmitFollowup = OnNanEventTransmitFollowup;

    if (mVM == NULL) {
        env->GetJavaVM(&mVM);
        mCls = (jclass) env->NewGlobalRef(cls);
    }

    return hal_fn.wifi_nan_register_handler(handle, handlers);
}

static jint android_net_wifi_nan_enable_request(JNIEnv *env, jclass cls,
                                                jshort transaction_id,
                                                jclass wifi_native_cls,
                                                jint iface,
                                                jobject config_request) {
    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

    ALOGD("android_net_wifi_nan_enable_request handle=%p, id=%d",
          handle, transaction_id);

    NanEnableRequest msg;
    memset(&msg, 0, sizeof(NanEnableRequest));

    /* configurable settings */
    msg.config_support_5g = 1;
    msg.support_5g_val = helper.getBoolField(config_request, "mSupport5gBand");
    msg.master_pref = helper.getIntField(config_request, "mMasterPreference");
    msg.cluster_low = helper.getIntField(config_request, "mClusterLow");
    msg.cluster_high = helper.getIntField(config_request, "mClusterHigh");

    return hal_fn.wifi_nan_enable_request(transaction_id, handle, &msg);
}

static jint android_net_wifi_nan_config_request(JNIEnv *env, jclass cls,
                                                jshort transaction_id,
                                                jclass wifi_native_cls,
                                                jint iface,
                                                jobject config_request) {
    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

    ALOGD("android_net_wifi_nan_config_request handle=%p, id=%d",
          handle, transaction_id);

    NanConfigRequest msg;
    memset(&msg, 0, sizeof(NanConfigRequest));

    /* configurable settings */
    msg.config_master_pref = 1;
    msg.master_pref = helper.getIntField(config_request, "mMasterPreference");

    return hal_fn.wifi_nan_config_request(transaction_id, handle, &msg);
}

static jint android_net_wifi_nan_get_capabilities(JNIEnv *env, jclass cls,
                                                  jshort transaction_id,
                                                  jclass wifi_native_cls,
                                                  jint iface) {
  JNIHelper helper(env);
  wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

  ALOGD("android_net_wifi_nan_get_capabilities handle=%p, id=%d", handle,
        transaction_id);

  return hal_fn.wifi_nan_get_capabilities(transaction_id, handle);
}

static jint android_net_wifi_nan_disable_request(JNIEnv *env, jclass cls,
                                                 jshort transaction_id,
                                                 jclass wifi_native_cls,
                                                 jint iface) {
    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

    ALOGD("android_net_wifi_nan_disable_request handle=%p, id=%d",
          handle, transaction_id);

    return hal_fn.wifi_nan_disable_request(transaction_id, handle);
}

static jint android_net_wifi_nan_publish(JNIEnv *env, jclass cls,
                                         jshort transaction_id,
                                         jint publish_id,
                                         jclass wifi_native_cls,
                                         jint iface,
                                         jobject publish_config) {
    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

    ALOGD("android_net_wifi_nan_publish handle=%p, id=%d", handle, transaction_id);

    NanPublishRequest msg;
    memset(&msg, 0, sizeof(NanPublishRequest));

    /* hard-coded settings - TBD: move to configurable */
    msg.period = 500;
    msg.publish_match_indicator = NAN_MATCH_ALG_MATCH_ONCE;
    msg.rssi_threshold_flag = 0;
    msg.connmap = 0;

    /* configurable settings */
    msg.publish_id = publish_id;

    JNIObject<jstring> objStr1 = helper.getStringField(publish_config, "mServiceName");
    if (objStr1 == NULL) {
        ALOGE("Error accessing mServiceName field");
        return 0;
    }
    ScopedUtfChars chars1(env, objStr1);
    const char *serviceName = chars1.c_str();
    if (serviceName == NULL) {
        ALOGE("Error getting mServiceName");
        return 0;
    }
    msg.service_name_len = strlen(serviceName);
    strcpy((char*)msg.service_name, serviceName);

    msg.service_specific_info_len = helper.getIntField(publish_config, "mServiceSpecificInfoLength");
    if (msg.service_specific_info_len != 0) {
        helper.getByteArrayField(publish_config, "mServiceSpecificInfo",
                             msg.service_specific_info, msg.service_specific_info_len);
    }


    msg.tx_match_filter_len = helper.getIntField(publish_config, "mTxFilterLength");
    if (msg.tx_match_filter_len != 0) {
        helper.getByteArrayField(publish_config, "mTxFilter",
                             msg.tx_match_filter, msg.tx_match_filter_len);
    }

    msg.rx_match_filter_len = helper.getIntField(publish_config, "mRxFilterLength");
    if (msg.rx_match_filter_len != 0) {
        helper.getByteArrayField(publish_config, "mRxFilter",
                             msg.rx_match_filter, msg.rx_match_filter_len);
    }

    msg.publish_type = (NanPublishType)helper.getIntField(publish_config, "mPublishType");
    msg.publish_count = helper.getIntField(publish_config, "mPublishCount");
    msg.ttl = helper.getIntField(publish_config, "mTtlSec");

    msg.tx_type = NAN_TX_TYPE_BROADCAST;
    if (msg.publish_type != NAN_PUBLISH_TYPE_UNSOLICITED)
      msg.tx_type = NAN_TX_TYPE_UNICAST;

    msg.recv_indication_cfg = 0;
    if (!helper.getBoolField(publish_config, "mEnableTerminateNotification")) {
      msg.recv_indication_cfg |= 0x1;
    }

    return hal_fn.wifi_nan_publish_request(transaction_id, handle, &msg);
}

static jint android_net_wifi_nan_subscribe(JNIEnv *env, jclass cls,
                                           jshort transaction_id,
                                           jint subscribe_id,
                                           jclass wifi_native_cls,
                                           jint iface,
                                           jobject subscribe_config) {
    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

    ALOGD("android_net_wifi_nan_subscribe handle=%p, id=%d", handle, transaction_id);

    NanSubscribeRequest msg;
    memset(&msg, 0, sizeof(NanSubscribeRequest));

    /* hard-coded settings - TBD: move to configurable */
    msg.period = 500;
    msg.serviceResponseFilter = NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
    msg.serviceResponseInclude = NAN_SRF_INCLUDE_RESPOND;
    msg.useServiceResponseFilter = NAN_DO_NOT_USE_SRF;
    msg.ssiRequiredForMatchIndication = NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
    msg.rssi_threshold_flag = 0;
    msg.connmap = 0;
    msg.num_intf_addr_present = 0;

    /* configurable settings */
    msg.subscribe_id = subscribe_id;

    JNIObject<jstring> objStr1 = helper.getStringField(subscribe_config, "mServiceName");
    if (objStr1 == NULL) {
        ALOGE("Error accessing mServiceName field");
        return 0;
    }
    ScopedUtfChars chars1(env, objStr1);
    const char *serviceName = chars1.c_str();
    if (serviceName == NULL) {
        ALOGE("Error getting mServiceName");
        return 0;
    }
    msg.service_name_len = strlen(serviceName);
    strcpy((char*)msg.service_name, serviceName);

    msg.service_specific_info_len = helper.getIntField(subscribe_config, "mServiceSpecificInfoLength");
    if (msg.service_specific_info_len != 0) {
        helper.getByteArrayField(subscribe_config, "mServiceSpecificInfo",
                             msg.service_specific_info, msg.service_specific_info_len);
    }

    msg.tx_match_filter_len = helper.getIntField(subscribe_config, "mTxFilterLength");
    if (msg.tx_match_filter_len != 0) {
        helper.getByteArrayField(subscribe_config, "mTxFilter",
                             msg.tx_match_filter, msg.tx_match_filter_len);
    }

    msg.rx_match_filter_len = helper.getIntField(subscribe_config, "mRxFilterLength");
    if (msg.rx_match_filter_len != 0) {
        helper.getByteArrayField(subscribe_config, "mRxFilter",
                             msg.rx_match_filter, msg.rx_match_filter_len);
    }

    msg.subscribe_type = (NanSubscribeType)helper.getIntField(subscribe_config, "mSubscribeType");
    msg.subscribe_count = helper.getIntField(subscribe_config, "mSubscribeCount");
    msg.ttl = helper.getIntField(subscribe_config, "mTtlSec");
    msg.subscribe_match_indicator = (NanMatchAlg) helper.getIntField(
      subscribe_config, "mMatchStyle");

    msg.recv_indication_cfg = 0;
    if (!helper.getBoolField(subscribe_config, "mEnableTerminateNotification")) {
      msg.recv_indication_cfg |= 0x1;
    }

    return hal_fn.wifi_nan_subscribe_request(transaction_id, handle, &msg);
}

static jint android_net_wifi_nan_send_message(JNIEnv *env, jclass cls,
                                              jshort transaction_id,
                                              jclass wifi_native_cls,
                                              jint iface,
                                              jint pub_sub_id,
                                              jint req_instance_id,
                                              jbyteArray dest,
                                              jbyteArray message,
                                              jint message_length) {
    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

    ALOGD("android_net_wifi_nan_send_message handle=%p, id=%d", handle, transaction_id);

    NanTransmitFollowupRequest msg;
    memset(&msg, 0, sizeof(NanTransmitFollowupRequest));

    /* hard-coded settings - TBD: move to configurable */
    msg.publish_subscribe_id = pub_sub_id;
    msg.requestor_instance_id = req_instance_id;
    msg.priority = NAN_TX_PRIORITY_NORMAL;
    msg.dw_or_faw = NAN_TRANSMIT_IN_DW;

    /* configurable settings */
    msg.service_specific_info_len = message_length;

    ScopedBytesRO messageBytes(env, message);
    memcpy(msg.service_specific_info, (byte*) messageBytes.get(), message_length);

    ScopedBytesRO destBytes(env, dest);
    memcpy(msg.addr, (byte*) destBytes.get(), 6);

    return hal_fn.wifi_nan_transmit_followup_request(transaction_id, handle, &msg);
}

static jint android_net_wifi_nan_stop_publish(JNIEnv *env, jclass cls,
                                              jshort transaction_id,
                                              jclass wifi_native_cls,
                                              jint iface,
                                              jint pub_sub_id) {
    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

    ALOGD("android_net_wifi_nan_stop_publish handle=%p, id=%d", handle, transaction_id);

    NanPublishCancelRequest msg;
    memset(&msg, 0, sizeof(NanPublishCancelRequest));

    msg.publish_id = pub_sub_id;

    return hal_fn.wifi_nan_publish_cancel_request(transaction_id, handle, &msg);
}

static jint android_net_wifi_nan_stop_subscribe(JNIEnv *env, jclass cls,
                                              jshort transaction_id,
                                              jclass wifi_native_cls,
                                              jint iface,
                                              jint pub_sub_id) {
    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);

    ALOGD("android_net_wifi_nan_stop_subscribe handle=%p, id=%d", handle, transaction_id);

    NanSubscribeCancelRequest msg;
    memset(&msg, 0, sizeof(NanSubscribeCancelRequest));

    msg.subscribe_id = pub_sub_id;

    return hal_fn.wifi_nan_subscribe_cancel_request(transaction_id, handle, &msg);
}

// ----------------------------------------------------------------------------

/*
 * JNI registration.
 */

static JNINativeMethod gWifiNanMethods[] = {
    /* name, signature, funcPtr */
    {"initNanHandlersNative", "(Ljava/lang/Class;I)I", (void*)android_net_wifi_nan_register_handler },
    {"getCapabilitiesNative", "(SLjava/lang/Class;I)I", (void*)android_net_wifi_nan_get_capabilities },
    {"enableAndConfigureNative", "(SLjava/lang/Class;ILandroid/net/wifi/nan/ConfigRequest;)I", (void*)android_net_wifi_nan_enable_request },
    {"updateConfigurationNative", "(SLjava/lang/Class;ILandroid/net/wifi/nan/ConfigRequest;)I", (void*)android_net_wifi_nan_config_request },
    {"disableNative", "(SLjava/lang/Class;I)I", (void*)android_net_wifi_nan_disable_request },
    {"publishNative", "(SILjava/lang/Class;ILandroid/net/wifi/nan/PublishConfig;)I", (void*)android_net_wifi_nan_publish },
    {"subscribeNative", "(SILjava/lang/Class;ILandroid/net/wifi/nan/SubscribeConfig;)I", (void*)android_net_wifi_nan_subscribe },
    {"sendMessageNative", "(SLjava/lang/Class;III[B[BI)I", (void*)android_net_wifi_nan_send_message },
    {"stopPublishNative", "(SLjava/lang/Class;II)I", (void*)android_net_wifi_nan_stop_publish },
    {"stopSubscribeNative", "(SLjava/lang/Class;II)I", (void*)android_net_wifi_nan_stop_subscribe },
};

/* User to register native functions */
extern "C"
jint Java_com_android_server_wifi_nan_WifiNanNative_registerNanNatives(JNIEnv* env, jclass clazz) {
    return jniRegisterNativeMethods(env,
            "com/android/server/wifi/nan/WifiNanNative", gWifiNanMethods, NELEM(gWifiNanMethods));
}

}; // namespace android
