| // 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" |
| |
| jutil "v.io/x/jni/util" |
| ) |
| |
| // #include "jni.h" |
| import "C" |
| |
| func NewBlePluginFactory(env jutil.Env, jAndroidContext jutil.Object) func(string) (idiscovery.Plugin, error) { |
| return newPluginFactory(env, jAndroidContext, jBlePluginClass) |
| } |
| |
| 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() |
| |
| jNativeScanHandler, err := jutil.NewObject(env, jNativeScanHandlerClass, []jutil.Sign{jutil.LongSign}, int64(jutil.PtrValue(&ch))) |
| if err != nil { |
| done() |
| return err |
| } |
| err = jutil.CallVoidMethod(env, p.jPlugin, "startScan", []jutil.Sign{jutil.StringSign, scanHandlerSign}, interfaceName, jNativeScanHandler) |
| if err != nil { |
| done() |
| return err |
| } |
| |
| jutil.GoRef(&ch) // Will be unrefed when jNativeScanHandler is finalized. |
| 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 newPluginFactory(env jutil.Env, jAndroidContext jutil.Object, jPluginClass jutil.Class) func(string) (idiscovery.Plugin, error) { |
| // Reference Android Context; it will be de-referenced when the factory |
| // is garbage-collected. |
| jAndroidContext = jutil.NewGlobalRef(env, jAndroidContext) |
| factory := func(host string) (idiscovery.Plugin, error) { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| |
| jHost := jutil.JString(env, host) |
| jPlugin, err := jutil.NewObject(env, jPluginClass, []jutil.Sign{jutil.StringSign, androidContextSign}, jHost, jAndroidContext) |
| 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 |
| } |
| runtime.SetFinalizer(factory, func(func(string) (idiscovery.Plugin, error)) { |
| env, freeFunc := jutil.GetEnv() |
| jutil.DeleteGlobalRef(env, jAndroidContext) |
| freeFunc() |
| }) |
| return factory |
| } |