blob: a4b960934d2802cac07429418fd3448926f466dd [file] [log] [blame]
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build android
package plugins
import (
"runtime"
"v.io/v23/context"
idiscovery "v.io/x/ref/lib/discovery"
dfactory "v.io/x/ref/lib/discovery/factory"
jutil "v.io/x/jni/util"
jcontext "v.io/x/jni/v23/context"
)
// #include "jni.h"
import "C"
type plugin struct {
jPlugin jutil.Object
trigger *idiscovery.Trigger
}
func (p *plugin) Advertise(ctx *context.T, adinfo *idiscovery.AdInfo, done func()) error {
env, freeFunc := jutil.GetEnv()
defer freeFunc()
jAdInfo, err := jutil.JVomCopy(env, adinfo, jAdInfoClass)
if err != nil {
done()
return err
}
err = jutil.CallVoidMethod(env, p.jPlugin, "startAdvertising", []jutil.Sign{adInfoSign}, jAdInfo)
if err != nil {
done()
return err
}
jAdInfo = jutil.NewGlobalRef(env, jAdInfo)
stop := func() {
env, freeFunc := jutil.GetEnv()
defer freeFunc()
jutil.CallVoidMethod(env, p.jPlugin, "stopAdvertising", []jutil.Sign{adInfoSign}, jAdInfo)
jutil.DeleteGlobalRef(env, jAdInfo)
done()
}
p.trigger.Add(stop, ctx.Done())
return nil
}
func (p *plugin) Scan(ctx *context.T, interfaceName string, ch chan<- *idiscovery.AdInfo, done func()) error {
env, freeFunc := jutil.GetEnv()
defer freeFunc()
chRef := jutil.GoNewRef(&ch) // Un-refed when jNativeScanHandler is finalized.
jNativeScanHandler, err := jutil.NewObject(env, jNativeScanHandlerClass, []jutil.Sign{jutil.LongSign}, int64(chRef))
if err != nil {
jutil.GoDecRef(chRef)
done()
return err
}
err = jutil.CallVoidMethod(env, p.jPlugin, "startScan", []jutil.Sign{jutil.StringSign, scanHandlerSign}, interfaceName, jNativeScanHandler)
if err != nil {
done()
return err
}
jNativeScanHandler = jutil.NewGlobalRef(env, jNativeScanHandler)
stop := func() {
env, freeFunc := jutil.GetEnv()
defer freeFunc()
jutil.CallVoidMethod(env, p.jPlugin, "stopScan", []jutil.Sign{scanHandlerSign}, jNativeScanHandler)
jutil.DeleteGlobalRef(env, jNativeScanHandler)
done()
}
p.trigger.Add(stop, ctx.Done())
return nil
}
func (p *plugin) Close() {
env, freeFunc := jutil.GetEnv()
defer freeFunc()
jutil.CallVoidMethod(env, p.jPlugin, "close", nil)
}
func newPluginFactory(env jutil.Env, jPluginClass jutil.Class) func(*context.T, string) (idiscovery.Plugin, error) {
return func(ctx *context.T, host string) (idiscovery.Plugin, error) {
env, freeFunc := jutil.GetEnv()
defer freeFunc()
// We pass the global context of the android vanadium runtime, since the context of the discovery
// factory does not have an Android context.
jCtx, err := jcontext.JavaContext(env, ctx, nil)
if err != nil {
return nil, err
}
jPlugin, err := jutil.NewObject(env, jPluginClass, []jutil.Sign{contextSign, jutil.StringSign}, jCtx, host)
if err != nil {
return nil, err
}
// Reference Plugin; it will be de-referenced when the plugin is garbage-collected.
jPlugin = jutil.NewGlobalRef(env, jPlugin)
p := &plugin{
jPlugin: jPlugin,
trigger: idiscovery.NewTrigger(),
}
runtime.SetFinalizer(p, func(*plugin) {
env, freeFunc := jutil.GetEnv()
jutil.DeleteGlobalRef(env, p.jPlugin)
freeFunc()
})
return p, nil
}
}
func initPluginFactories(env jutil.Env) error {
jPluginClass, err := jutil.JFindClass(env, "io/v/android/impl/google/discovery/plugins/ble/BlePlugin")
if err != nil {
return err
}
dfactory.SetPluginFactory("ble", newPluginFactory(env, jPluginClass))
return nil
}