discovery: android BLE driver
Add android BLE driver.
MultiPart: 1/3
Change-Id: I05ef4a2bd5ee8caeda375f9c3ef873222a06d5c9
diff --git a/impl/google/discovery/plugins/ble/driver.go b/impl/google/discovery/plugins/ble/driver.go
new file mode 100644
index 0000000..0424cbf
--- /dev/null
+++ b/impl/google/discovery/plugins/ble/driver.go
@@ -0,0 +1,116 @@
+// 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 ble
+
+import (
+ "runtime"
+
+ "v.io/v23/context"
+
+ "v.io/x/ref/lib/discovery/plugins/ble"
+
+ jutil "v.io/x/jni/util"
+ jcontext "v.io/x/jni/v23/context"
+)
+
+// #include "jni.h"
+import "C"
+
+type driver struct {
+ jDriver jutil.Object
+}
+
+func (d *driver) AddService(uuid string, characteristics map[string][]byte) error {
+ env, freeFunc := jutil.GetEnv()
+ defer freeFunc()
+
+ csObjMap := make(map[jutil.Object]jutil.Object, len(characteristics))
+ for uuid, characteristic := range characteristics {
+ jUuid := jutil.JString(env, uuid)
+ jCharacteristic, err := jutil.JByteArray(env, characteristic)
+ if err != nil {
+ return err
+ }
+ csObjMap[jUuid] = jCharacteristic
+ }
+ jCharacteristics, err := jutil.JObjectMap(env, csObjMap)
+ if err != nil {
+ return err
+ }
+ return jutil.CallVoidMethod(env, d.jDriver, "addService", []jutil.Sign{jutil.StringSign, jutil.MapSign}, uuid, jCharacteristics)
+}
+
+func (d *driver) RemoveService(uuid string) {
+ env, freeFunc := jutil.GetEnv()
+ defer freeFunc()
+
+ jutil.CallVoidMethod(env, d.jDriver, "removeService", []jutil.Sign{jutil.StringSign}, uuid)
+}
+
+func (d *driver) StartScan(uuids []string, baseUuid, maskUuid string, handler ble.ScanHandler) error {
+ env, freeFunc := jutil.GetEnv()
+ defer freeFunc()
+
+ handlerRef := jutil.GoNewRef(&handler) // Un-refed when jNativeScanHandler is finalized.
+ jNativeScanHandler, err := jutil.NewObject(env, jNativeScanHandlerClass, []jutil.Sign{jutil.LongSign}, int64(handlerRef))
+ if err != nil {
+ jutil.GoDecRef(handlerRef)
+ return err
+ }
+ err = jutil.CallVoidMethod(env, d.jDriver, "startScan", []jutil.Sign{jutil.ArraySign(jutil.StringSign), jutil.StringSign, jutil.StringSign, scanHandlerSign}, uuids, baseUuid, maskUuid, jNativeScanHandler)
+ if err != nil {
+ jutil.GoDecRef(handlerRef)
+ return err
+ }
+ return nil
+}
+
+func (d *driver) StopScan() {
+ env, freeFunc := jutil.GetEnv()
+ defer freeFunc()
+
+ jutil.CallVoidMethod(env, d.jDriver, "stopScan", nil)
+}
+
+func (d *driver) DebugString() string {
+ env, freeFunc := jutil.GetEnv()
+ defer freeFunc()
+
+ s, _ := jutil.CallStringMethod(env, d.jDriver, "debugString", nil)
+ return s
+}
+
+func initDriverFactory(env jutil.Env) error {
+ jDriverClass, err := jutil.JFindClass(env, "io/v/android/impl/google/discovery/plugins/ble/Driver")
+ if err != nil {
+ return err
+ }
+ factory := func(ctx *context.T, _ string) (ble.Driver, error) {
+ env, freeFunc := jutil.GetEnv()
+ defer freeFunc()
+
+ jCtx, err := jcontext.JavaContext(env, ctx, nil)
+ if err != nil {
+ return nil, err
+ }
+ jDriver, err := jutil.NewObject(env, jDriverClass, []jutil.Sign{contextSign}, jCtx)
+ if err != nil {
+ return nil, err
+ }
+ // Reference the driver; it will be de-referenced when the driver is garbage-collected.
+ jDriver = jutil.NewGlobalRef(env, jDriver)
+ d := &driver{jDriver}
+ runtime.SetFinalizer(d, func(*driver) {
+ env, freeFunc := jutil.GetEnv()
+ jutil.DeleteGlobalRef(env, d.jDriver)
+ freeFunc()
+ })
+ return d, nil
+ }
+ ble.SetDriverFactory(factory)
+ return nil
+}
diff --git a/impl/google/discovery/plugins/ble/jni.go b/impl/google/discovery/plugins/ble/jni.go
new file mode 100644
index 0000000..f51b424
--- /dev/null
+++ b/impl/google/discovery/plugins/ble/jni.go
@@ -0,0 +1,57 @@
+// 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 ble
+
+import (
+ "unsafe"
+
+ "v.io/x/ref/lib/discovery/plugins/ble"
+
+ jutil "v.io/x/jni/util"
+)
+
+// #include "jni.h"
+import "C"
+
+var (
+ contextSign = jutil.ClassSign("io.v.v23.context.VContext")
+ scanHandlerSign = jutil.ClassSign("io.v.android.impl.google.discovery.plugins.ble.Driver$ScanHandler")
+
+ jNativeScanHandlerClass jutil.Class // io.v.android.impl.google.discovery.plugins.ble.NativeScanHandler
+)
+
+func Init(env jutil.Env) error {
+ var err error
+ jNativeScanHandlerClass, err = jutil.JFindClass(env, "io/v/android/impl/google/discovery/plugins/ble/NativeScanHandler")
+ if err != nil {
+ return err
+ }
+ return initDriverFactory(env)
+}
+
+//export Java_io_v_android_impl_google_discovery_plugins_ble_NativeScanHandler_nativeOnDiscovered
+func Java_io_v_android_impl_google_discovery_plugins_ble_NativeScanHandler_nativeOnDiscovered(jenv *C.JNIEnv, _ C.jobject, handlerRef C.jlong, jUuid C.jstring, jCharacteristics C.jobject, jRssi C.jint) {
+ env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
+ scanHandler := (*(*ble.ScanHandler)(jutil.GoRefValue(jutil.Ref(handlerRef))))
+ uuid := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jUuid))))
+ csObjMap, err := jutil.GoObjectMap(env, jutil.Object(uintptr(unsafe.Pointer(jCharacteristics))))
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return
+ }
+ characteristics := make(map[string][]byte, len(csObjMap))
+ for jUuid, jCharacteristic := range csObjMap {
+ characteristics[jutil.GoString(env, jUuid)] = jutil.GoByteArray(env, jCharacteristic)
+ }
+ rssi := int(jRssi)
+ scanHandler.OnDiscovered(uuid, characteristics, rssi)
+}
+
+//export Java_io_v_android_impl_google_discovery_plugins_ble_NativeScanHandler_nativeFinalize
+func Java_io_v_android_impl_google_discovery_plugins_ble_NativeScanHandler_nativeFinalize(_ *C.JNIEnv, _ C.jobject, handlerRef C.jlong) {
+ jutil.GoDecRef(jutil.Ref(handlerRef))
+}
diff --git a/impl/google/discovery/plugins/jni.go b/impl/google/discovery/plugins/jni.go
index 9f171c6..48f6706 100644
--- a/impl/google/discovery/plugins/jni.go
+++ b/impl/google/discovery/plugins/jni.go
@@ -7,55 +7,11 @@
package plugins
import (
- "unsafe"
-
- idiscovery "v.io/x/ref/lib/discovery"
+ "v.io/x/jni/impl/google/discovery/plugins/ble"
jutil "v.io/x/jni/util"
)
-// #include "jni.h"
-import "C"
-
-var (
- contextSign = jutil.ClassSign("io.v.v23.context.VContext")
- adInfoSign = jutil.ClassSign("io.v.x.ref.lib.discovery.AdInfo")
- scanHandlerSign = jutil.ClassSign("io.v.impl.google.lib.discovery.Plugin$ScanHandler")
-
- jAdInfoClass jutil.Class // io.v.x.ref.lib.discovery.AdInfo
- jNativeScanHandlerClass jutil.Class // io.v.android.impl.google.discovery.plugins.NativeScanHandler
-)
-
func Init(env jutil.Env) error {
- var err error
- jAdInfoClass, err = jutil.JFindClass(env, "io/v/x/ref/lib/discovery/AdInfo")
- if err != nil {
- return err
- }
- jNativeScanHandlerClass, err = jutil.JFindClass(env, "io/v/android/impl/google/discovery/plugins/NativeScanHandler")
- if err != nil {
- return err
- }
-
- return initPluginFactories(env)
-}
-
-//export Java_io_v_android_impl_google_discovery_plugins_NativeScanHandler_nativeHandleUpdate
-func Java_io_v_android_impl_google_discovery_plugins_NativeScanHandler_nativeHandleUpdate(jenv *C.JNIEnv, _ C.jobject, goRef C.jlong, jAdInfoObj C.jobject) {
- env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
- ch := (*(*chan<- *idiscovery.AdInfo)(jutil.GoRefValue(jutil.Ref(goRef))))
-
- jAdInfo := jutil.Object(uintptr(unsafe.Pointer(jAdInfoObj)))
-
- var adInfo idiscovery.AdInfo
- if err := jutil.GoVomCopy(env, jAdInfo, jAdInfoClass, &adInfo); err != nil {
- jutil.JThrowV(env, err)
- return
- }
- ch <- &adInfo
-}
-
-//export Java_io_v_android_impl_google_discovery_plugins_NativeScanHandler_nativeFinalize
-func Java_io_v_android_impl_google_discovery_plugins_NativeScanHandler_nativeFinalize(jenv *C.JNIEnv, _ C.jobject, goRef C.jlong) {
- jutil.GoDecRef(jutil.Ref(goRef))
+ return ble.Init(env)
}
diff --git a/impl/google/discovery/plugins/plugin.go b/impl/google/discovery/plugins/plugin.go
deleted file mode 100644
index a4b9609..0000000
--- a/impl/google/discovery/plugins/plugin.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// 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
-}