Merge "jni: Validate v.io/v23/security/access.AccessTagCaveat in Java"
diff --git a/impl/google/discovery/jni.go b/impl/google/discovery/jni.go
index 77dab52..666c9f1 100644
--- a/impl/google/discovery/jni.go
+++ b/impl/google/discovery/jni.go
@@ -7,14 +7,12 @@
package discovery
import (
- "bytes"
- "encoding/binary"
"unsafe"
- "v.io/v23/context"
"v.io/v23/discovery"
"v.io/v23/security"
"v.io/v23/verror"
+
idiscovery "v.io/x/ref/lib/discovery"
jchannel "v.io/x/jni/impl/google/channel"
@@ -27,26 +25,15 @@
import "C"
var (
- updateSign = jutil.ClassSign("io.v.v23.discovery.Update")
- contextSign = jutil.ClassSign("io.v.v23.context.VContext")
+ adIdSign = jutil.ClassSign("io.v.v23.discovery.AdId")
+ advertisementSign = jutil.ClassSign("io.v.v23.discovery.Advertisement")
- // Global reference for java.util.UUID class.
- jUUIDClass jutil.Class
-
- // Global reference io.v.impl.google.lib.discovery.ScanHandler
- jScanHandlerClass jutil.Class
-
- // Global reference io.v.v23.discovery.Service
- jServiceClass jutil.Class
-
- // Global reference io.v.v23.security.BlessingPattern
- jBlessingPatternClass jutil.Class
-
- // Global reference io.v.v23.discovery.Update
- jUpdateClass jutil.Class
-
- // Global reference io.v.impl.google.lib.discovery.VDiscoveryImpl
- jVDiscoveryImplClass jutil.Class
+ jAdIdClass jutil.Class // io.v.v23.discovery.AdId
+ jAdvertisementClass jutil.Class // io.v.v23.discovery.Advertisement
+ jBlessingPatternClass jutil.Class // io.v.v23.security.BlessingPattern
+ jDiscoveryImplClass jutil.Class // io.v.impl.google.lib.discovery.DiscoveryImpl
+ jUpdateImplClass jutil.Class // io.v.impl.google.lib.discovery.UpdateImpl
+ jUUIDClass jutil.Class // java.util.UUID
)
// Init initializes the JNI code with the given Java environment. This method
@@ -56,15 +43,11 @@
// necessary because JNI gets access to the class loader only in the system
// thread, so we aren't able to invoke FindClass in other threads.
var err error
- jUUIDClass, err = jutil.JFindClass(env, "java/util/UUID")
+ jAdIdClass, err = jutil.JFindClass(env, "io/v/v23/discovery/AdId")
if err != nil {
return err
}
- jScanHandlerClass, err = jutil.JFindClass(env, "io/v/impl/google/lib/discovery/ScanHandler")
- if err != nil {
- return err
- }
- jServiceClass, err = jutil.JFindClass(env, "io/v/v23/discovery/Service")
+ jAdvertisementClass, err = jutil.JFindClass(env, "io/v/v23/discovery/Advertisement")
if err != nil {
return err
}
@@ -72,159 +55,135 @@
if err != nil {
return err
}
- jUpdateClass, err = jutil.JFindClass(env, "io/v/v23/discovery/Update")
+ jDiscoveryImplClass, err = jutil.JFindClass(env, "io/v/impl/google/lib/discovery/DiscoveryImpl")
if err != nil {
return err
}
-
- jVDiscoveryImplClass, err = jutil.JFindClass(env, "io/v/impl/google/lib/discovery/VDiscoveryImpl")
+ jUpdateImplClass, err = jutil.JFindClass(env, "io/v/impl/google/lib/discovery/UpdateImpl")
if err != nil {
return err
}
-
+ jUUIDClass, err = jutil.JFindClass(env, "java/util/UUID")
+ if err != nil {
+ return err
+ }
return nil
}
-func convertStringtoUUID(jenv *C.JNIEnv, _ C.jclass, jName C.jstring, generator func(string) idiscovery.Uuid) C.jobject {
+//export Java_io_v_impl_google_lib_discovery_UUIDUtil_serviceUUID
+func Java_io_v_impl_google_lib_discovery_UUIDUtil_serviceUUID(jenv *C.JNIEnv, _ C.jclass, jName C.jstring) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
name := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
- uuid := generator(name)
- buf := bytes.NewBuffer(uuid)
- var high, low int64
- binary.Read(buf, binary.BigEndian, &high)
- binary.Read(buf, binary.BigEndian, &low)
- jUUID, err := jutil.NewObject(env, jUUIDClass, []jutil.Sign{jutil.LongSign, jutil.LongSign}, high, low)
+ jUuid, err := javaUUID(env, idiscovery.NewServiceUUID(name))
if err != nil {
jutil.JThrowV(env, err)
return nil
}
- return C.jobject(unsafe.Pointer(jUUID))
+ return C.jobject(unsafe.Pointer(jUuid))
}
-//export Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForInterfaceName
-func Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForInterfaceName(jenv *C.JNIEnv, jclass C.jclass, jName C.jstring) C.jobject {
- return convertStringtoUUID(jenv, jclass, jName, idiscovery.NewServiceUUID)
-}
-
-//export Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForAttributeKey
-func Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForAttributeKey(jenv *C.JNIEnv, jclass C.jclass, jName C.jstring) C.jobject {
- converter := func(s string) idiscovery.Uuid {
- return idiscovery.NewAttributeUUID(s)
- }
- return convertStringtoUUID(jenv, jclass, jName, converter)
-}
-
-func doAdvertise(ctx *context.T, ds discovery.T, trigger *idiscovery.Trigger, service discovery.Service, visibility []security.BlessingPattern, jService jutil.Object, jDoneCallback jutil.Object) (jutil.Object, error) {
- // Blocking call, so don't call GetEnv() beforehand.
- done, err := ds.Advertise(ctx, &service, visibility)
- env, freeFunc := jutil.GetEnv()
- defer freeFunc()
- defer jutil.DeleteGlobalRef(env, jService)
- if err != nil {
- jutil.DeleteGlobalRef(env, jDoneCallback)
- return jutil.NullObject, err
- }
- // Copy back service.InstanceId to jService since it's the only field that would be updated.
- if err = jutil.CallVoidMethod(env, jService, "setInstanceId", []jutil.Sign{jutil.StringSign}, service.InstanceId); err != nil {
- jutil.DeleteGlobalRef(env, jDoneCallback)
- return jutil.NullObject, err
- }
- jContext, err := jcontext.JavaContext(env, ctx, nil)
- if err != nil {
- return jutil.NullObject, err
- }
- listenableFutureSign := jutil.ClassSign("com.google.common.util.concurrent.ListenableFuture")
- jDoneFuture, err := jutil.CallObjectMethod(env, jDoneCallback, "getFuture", []jutil.Sign{contextSign}, listenableFutureSign, jContext)
- if err != nil {
- jutil.DeleteGlobalRef(env, jDoneCallback)
- return jutil.NullObject, err
- }
- trigger.Add(func() {
- env, freeFunc := jutil.GetEnv()
- defer freeFunc()
- jutil.CallbackOnSuccess(env, jDoneCallback, jutil.NullObject)
- jutil.DeleteGlobalRef(env, jDoneCallback)
- }, done)
- // Must grab a global reference as we free up the env and all local references that come along
- // with it.
- return jutil.NewGlobalRef(env, jDoneFuture), nil // Un-refed in DoAsyncCall
-}
-
-//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeAdvertise
-func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeAdvertise(jenv *C.JNIEnv, jDiscovery C.jobject, goDiscoveryPtr C.jlong, goTriggerPtr C.jlong, jContext C.jobject, jServiceObj C.jobject, jVisibilityObj C.jobject, jStartCallbackObj C.jobject, jDoneCallbackObj C.jobject) {
+//export Java_io_v_impl_google_lib_discovery_UUIDUtil_attributeUUID
+func Java_io_v_impl_google_lib_discovery_UUIDUtil_attributeUUID(jenv *C.JNIEnv, _ C.jclass, jName C.jstring) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
- jService := jutil.Object(uintptr(unsafe.Pointer(jServiceObj)))
+ name := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
+ jUuid, err := javaUUID(env, idiscovery.NewAttributeUUID(name))
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return nil
+ }
+ return C.jobject(unsafe.Pointer(jUuid))
+}
+
+//export Java_io_v_impl_google_lib_discovery_DiscoveryImpl_nativeAdvertise
+func Java_io_v_impl_google_lib_discovery_DiscoveryImpl_nativeAdvertise(jenv *C.JNIEnv, _ C.jobject, dPtr C.jlong, jCtx C.jobject, jAdObj C.jobject, jVisibilityObj C.jobject, jCbObj C.jobject) {
+ env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
+ ctx, _, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jCtx))))
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return
+ }
+
+ d := *(*discovery.T)(jutil.NativePtr(dPtr))
+ jAd := jutil.Object(uintptr(unsafe.Pointer(jAdObj)))
jVisibility := jutil.Object(uintptr(unsafe.Pointer(jVisibilityObj)))
- jStartCallback := jutil.Object(uintptr(unsafe.Pointer(jStartCallbackObj)))
- jDoneCallback := jutil.Object(uintptr(unsafe.Pointer(jDoneCallbackObj)))
- ctx, _, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
+
+ var ad discovery.Advertisement
+ if err := jutil.GoVomCopy(env, jAd, jAdvertisementClass, &ad); err != nil {
+ jutil.JThrowV(env, err)
+ return
+ }
+
+ jVisibilityList, err := jutil.GoObjectList(env, jVisibility)
if err != nil {
- jutil.CallbackOnFailure(env, jStartCallback, err)
+ jutil.JThrowV(env, err)
return
}
- var service discovery.Service
- if err := jutil.GoVomCopy(env, jService, jServiceClass, &service); err != nil {
- jutil.CallbackOnFailure(env, jStartCallback, err)
- return
- }
- varr, err := jutil.GoObjectList(env, jVisibility)
- if err != nil {
- jutil.CallbackOnFailure(env, jStartCallback, err)
- return
- }
- visibility := make([]security.BlessingPattern, len(varr))
- for i, jPattern := range varr {
+ visibility := make([]security.BlessingPattern, len(jVisibilityList))
+ for i, jPattern := range jVisibilityList {
if err := jutil.GoVomCopy(env, jPattern, jBlessingPatternClass, &visibility[i]); err != nil {
- jutil.CallbackOnFailure(env, jStartCallback, err)
+ jutil.JThrowV(env, err)
return
}
}
- ds := *(*discovery.T)(jutil.NativePtr(goDiscoveryPtr))
- trigger := (*idiscovery.Trigger)(jutil.NativePtr(goTriggerPtr))
- jService = jutil.NewGlobalRef(env, jService) // Un-refed in doAdvertise
- jDoneCallback = jutil.NewGlobalRef(env, jDoneCallback) // Un-refed in doAdvertise
- jutil.DoAsyncCall(env, jStartCallback, func() (jutil.Object, error) {
- return doAdvertise(ctx, ds, trigger, service, visibility, jService, jDoneCallback)
+
+ done, err := d.Advertise(ctx, &ad, visibility)
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return
+ }
+
+ // Copy back the advertisement id.
+ jId, err := jutil.JVomCopy(env, &ad.Id, jAdIdClass)
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return
+ }
+ if err = jutil.CallVoidMethod(env, jAd, "setId", []jutil.Sign{adIdSign}, jId); err != nil {
+ jutil.JThrowV(env, err)
+ return
+ }
+
+ jCb := jutil.Object(uintptr(unsafe.Pointer(jCbObj)))
+ jutil.DoAsyncCall(env, jCb, func() (jutil.Object, error) {
+ <-done
+ return jutil.NullObject, nil
})
}
-//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeScan
-func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeScan(jenv *C.JNIEnv, jDiscovery C.jobject, goDiscoveryPtr C.jlong, jContext C.jobject, jQuery C.jstring) C.jobject {
+//export Java_io_v_impl_google_lib_discovery_DiscoveryImpl_nativeScan
+func Java_io_v_impl_google_lib_discovery_DiscoveryImpl_nativeScan(jenv *C.JNIEnv, _ C.jobject, dPtr C.jlong, jCtx C.jobject, jQuery C.jstring) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
- ctx, cancel, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
+ ctx, _, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jCtx))))
if err != nil {
jutil.JThrowV(env, err)
return nil
}
- query := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jQuery))))
- ds := *(*discovery.T)(jutil.NativePtr(goDiscoveryPtr))
- var scanChannel <-chan discovery.Update
- var scanError error
- scanDone := make(chan bool)
- go func() {
- scanChannel, scanError = ds.Scan(ctx, query)
- close(scanDone)
- }()
- jChannel, err := jchannel.JavaInputChannel(env, ctx, cancel, func() (jutil.Object, error) {
- // A few blocking calls below - don't call GetEnv() before they complete.
- <-scanDone
- if scanError != nil {
- return jutil.NullObject, scanError
- }
- update, ok := <-scanChannel
+ d := *(*discovery.T)(jutil.NativePtr(dPtr))
+ query := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jQuery))))
+
+ scanCh, err := d.Scan(ctx, query)
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return nil
+ }
+
+ jChannel, err := jchannel.JavaInputChannel(env, ctx, nil, func() (jutil.Object, error) {
+ update, ok := <-scanCh
if !ok {
return jutil.NullObject, verror.NewErrEndOfFile(ctx)
}
+
env, freeFunc := jutil.GetEnv()
defer freeFunc()
- jUpdate, err := jutil.JVomCopy(env, update, jUpdateClass)
+
+ jUpdate, err := javaUpdate(env, update)
if err != nil {
return jutil.NullObject, err
}
// Must grab a global reference as we free up the env and all local references that come
// along with it.
- return jutil.NewGlobalRef(env, jUpdate), nil // Un-refed by InputChannelImpl_nativeRecv
+ return jutil.NewGlobalRef(env, jUpdate), nil // un-refed by InputChannelImpl_nativeRecv
})
if err != nil {
jutil.JThrowV(env, err)
@@ -233,8 +192,55 @@
return C.jobject(unsafe.Pointer(jChannel))
}
-//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeFinalize
-func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeFinalize(jenv *C.JNIEnv, jDiscovery C.jobject, goDiscoveryPtr C.jlong, goTriggerPtr C.jlong) {
- jutil.GoUnref(jutil.NativePtr(goDiscoveryPtr))
- jutil.GoUnref(jutil.NativePtr(goTriggerPtr))
+//export Java_io_v_impl_google_lib_discovery_DiscoveryImpl_nativeFinalize
+func Java_io_v_impl_google_lib_discovery_DiscoveryImpl_nativeFinalize(jenv *C.JNIEnv, _ C.jobject, dPtr C.jlong) {
+ jutil.GoUnref(jutil.NativePtr(dPtr))
+}
+
+//export Java_io_v_impl_google_lib_discovery_UpdateImpl_nativeAttachment
+func Java_io_v_impl_google_lib_discovery_UpdateImpl_nativeAttachment(jenv *C.JNIEnv, _ C.jobject, uPtr C.jlong, jCtx C.jobject, jName C.jstring, jCbObj C.jobject) {
+ env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
+ ctx, _, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jCtx))))
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return
+ }
+
+ update := *(*discovery.Update)(jutil.NativePtr(uPtr))
+ name := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
+
+ jCb := jutil.Object(uintptr(unsafe.Pointer(jCbObj)))
+ jutil.DoAsyncCall(env, jCb, func() (jutil.Object, error) {
+ dataOrErr := <-update.Attachment(ctx, name)
+ if dataOrErr.Error != nil {
+ return jutil.NullObject, err
+ }
+
+ env, freeFunc := jutil.GetEnv()
+ defer freeFunc()
+
+ jData, err := jutil.JByteArray(env, dataOrErr.Data)
+ if err != nil {
+ return jutil.NullObject, err
+ }
+ // Must grab a global reference as we free up the env and all local references that come
+ // along with it.
+ return jutil.NewGlobalRef(env, jData), nil // Un-refed in DoAsyncCall
+ })
+}
+
+//export Java_io_v_impl_google_lib_discovery_UpdateImpl_nativeFinalize
+func Java_io_v_impl_google_lib_discovery_UpdateImpl_nativeFinalize(jenv *C.JNIEnv, _ C.jobject, uPtr C.jlong) {
+ jutil.GoUnref(jutil.NativePtr(uPtr))
+}
+
+//export Java_io_v_impl_google_lib_discovery_DiscoveryTestUtil_injectMockDiscovery
+func Java_io_v_impl_google_lib_discovery_DiscoveryTestUtil_injectMockDiscovery(jenv *C.JNIEnv, _ C.jclass, jCtx C.jobject) {
+ env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
+ ctx, _, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jCtx))))
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return
+ }
+ injectMockDiscovery(ctx)
}
diff --git a/impl/google/discovery/plugins/jni.go b/impl/google/discovery/plugins/jni.go
new file mode 100644
index 0000000..7687b42
--- /dev/null
+++ b/impl/google/discovery/plugins/jni.go
@@ -0,0 +1,65 @@
+// 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 (
+ "unsafe"
+
+ idiscovery "v.io/x/ref/lib/discovery"
+
+ jutil "v.io/x/jni/util"
+)
+
+// #include "jni.h"
+import "C"
+
+var (
+ androidContextSign = jutil.ClassSign("android.content.Context")
+ 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
+ jBlePluginClass jutil.Class // io.v.android.impl.google.discovery.plugins.ble.BlePlugin
+)
+
+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
+ }
+ jBlePluginClass, err = jutil.JFindClass(env, "io/v/android/impl/google/discovery/plugins/ble/BlePlugin")
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+//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, chPtr C.jlong, jAdInfoObj C.jobject) {
+ env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
+ ch := (*(*chan<- *idiscovery.AdInfo)(jutil.NativePtr(chPtr)))
+
+ 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, chPtr C.jlong) {
+ jutil.GoUnref(jutil.NativePtr(chPtr))
+}
diff --git a/impl/google/discovery/plugins/plugin.go b/impl/google/discovery/plugins/plugin.go
new file mode 100644
index 0000000..06b1eb1
--- /dev/null
+++ b/impl/google/discovery/plugins/plugin.go
@@ -0,0 +1,120 @@
+// 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()
+ defer freeFunc()
+ jutil.DeleteGlobalRef(env, jAndroidContext)
+ })
+ return factory
+}
diff --git a/impl/google/discovery/util.go b/impl/google/discovery/util.go
index 65566d9..b776ea8 100644
--- a/impl/google/discovery/util.go
+++ b/impl/google/discovery/util.go
@@ -7,25 +7,58 @@
package discovery
import (
- jutil "v.io/x/jni/util"
+ "bytes"
+ "encoding/binary"
+ "v.io/v23/context"
"v.io/v23/discovery"
- idiscovery "v.io/x/ref/lib/discovery"
-)
-// #include "jni.h"
-import "C"
+ idiscovery "v.io/x/ref/lib/discovery"
+ fdiscovery "v.io/x/ref/lib/discovery/factory"
+ "v.io/x/ref/lib/discovery/plugins/mock"
+
+ jutil "v.io/x/jni/util"
+)
// JavaDiscovery converts a Go discovery instance into a Java discovery instance.
func JavaDiscovery(env jutil.Env, d discovery.T) (jutil.Object, error) {
- trigger := idiscovery.NewTrigger()
- // These reference will get unrefed when the jDiscovery object below is finalized.
- jutil.GoRef(trigger)
- jutil.GoRef(&d)
-
- jDiscovery, err := jutil.NewObject(env, jVDiscoveryImplClass, []jutil.Sign{jutil.LongSign, jutil.LongSign}, int64(jutil.PtrValue(&d)), int64(jutil.PtrValue(trigger)))
+ jDiscovery, err := jutil.NewObject(env, jDiscoveryImplClass, []jutil.Sign{jutil.LongSign}, int64(jutil.PtrValue(&d)))
if err != nil {
return jutil.NullObject, err
}
+ jutil.GoRef(&d) // Will be unrefed when jDiscovery is finalized.
return jDiscovery, nil
}
+
+// javaUpdate converts a Go update instance into a Java update instance.
+func javaUpdate(env jutil.Env, update discovery.Update) (jutil.Object, error) {
+ jAd, err := jutil.JVomCopy(env, update.Advertisement(), jAdvertisementClass)
+ if err != nil {
+ return jutil.NullObject, err
+ }
+ jUpdate, err := jutil.NewObject(env, jUpdateImplClass, []jutil.Sign{jutil.LongSign, jutil.BoolSign, advertisementSign}, int64(jutil.PtrValue(&update)), update.IsLost(), jAd)
+ if err != nil {
+ return jutil.NullObject, err
+ }
+ jutil.GoRef(&update) // Will be unrefed when jUpdate is finalized.
+ return jUpdate, nil
+}
+
+// javaUUID converts a Go UUID into a Java UUID instance.
+func javaUUID(env jutil.Env, uuid idiscovery.Uuid) (jutil.Object, error) {
+ var high, low int64
+ buf := bytes.NewReader(uuid)
+ binary.Read(buf, binary.BigEndian, &high)
+ binary.Read(buf, binary.BigEndian, &low)
+ return jutil.NewObject(env, jUUIDClass, []jutil.Sign{jutil.LongSign, jutil.LongSign}, high, low)
+}
+
+// injectMockDiscovery injects a discovery instance with a mock plugin into a runtime.
+func injectMockDiscovery(ctx *context.T) error {
+ df, err := idiscovery.NewFactory(ctx, mock.New())
+ if err != nil {
+ return err
+ }
+ fdiscovery.InjectFactory(df)
+ return nil
+}
diff --git a/jni_android.go b/jni_android.go
index d853f68..3c87303 100644
--- a/jni_android.go
+++ b/jni_android.go
@@ -10,10 +10,10 @@
"unsafe"
"v.io/x/lib/vlog"
- "v.io/x/ref/lib/discovery/factory"
+ dfactory "v.io/x/ref/lib/discovery/factory"
_ "v.io/x/ref/runtime/factories/android"
- jdiscovery "v.io/x/jni/libs/discovery"
+ jdplugins "v.io/x/jni/impl/google/discovery/plugins"
jutil "v.io/x/jni/util"
)
@@ -35,10 +35,10 @@
// This assumes that vlog.Log is the underlying logging system for.
vlog.Log.Configure(vlog.OverridePriorConfiguration(true), vlog.LogToStderr(false), vlog.AlsoLogToStderr(false), level, vmodule)
- // Setup discovery.
- if err := jdiscovery.Init(env); err != nil {
+ // Setup discovery plugins.
+ if err := jdplugins.Init(env); err != nil {
jutil.JThrowV(env, err)
return
}
- factory.SetBleFactory(jdiscovery.NewBleCreator(env, jutil.Object(uintptr(unsafe.Pointer(jAndroidContext)))))
+ dfactory.SetBleFactory(jdplugins.NewBlePluginFactory(env, jutil.Object(uintptr(unsafe.Pointer(jAndroidContext)))))
}
diff --git a/libs/discovery/jni.go b/libs/discovery/jni.go
deleted file mode 100644
index b9a1c27..0000000
--- a/libs/discovery/jni.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2015 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 discovery
-
-import (
- "unsafe"
-
- jutil "v.io/x/jni/util"
- "v.io/x/ref/lib/discovery"
-)
-
-// #include "jni.h"
-import "C"
-
-var (
- androidContextSign = jutil.ClassSign("android.content.Context")
- contextSign = jutil.ClassSign("io.v.v23.context.VContext")
- advertisementSign = jutil.ClassSign("io.v.x.ref.lib.discovery.Advertisement")
- scanHandlerSign = jutil.ClassSign("io.v.impl.google.lib.discovery.ScanHandler")
-
- // Global reference for io.v.x.ref.lib.discovery.Advertisement
- jAdvertisementClass jutil.Class
- // Global reference for io.v.android.libs.discovery.ble.BlePlugin
- jBlePluginClass jutil.Class
- // Global reference for io.v.android.libs.discovery.ble.NativeScanHandler
- jNativeScanHandlerClass jutil.Class
-)
-
-func Init(env jutil.Env) error {
- var err error
-
- jAdvertisementClass, err = jutil.JFindClass(env, "io/v/x/ref/lib/discovery/Advertisement")
- if err != nil {
- return err
- }
- jBlePluginClass, err = jutil.JFindClass(env, "io/v/android/libs/discovery/ble/BlePlugin")
- if err != nil {
- return err
- }
- jNativeScanHandlerClass, err = jutil.JFindClass(env, "io/v/android/libs/discovery/ble/NativeScanHandler")
- return err
-}
-
-//export Java_io_v_android_libs_discovery_ble_NativeScanHandler_nativeHandleUpdate
-func Java_io_v_android_libs_discovery_ble_NativeScanHandler_nativeHandleUpdate(jenv *C.JNIEnv, _ C.jobject, jAdvObj C.jobject, goPtr C.jlong) {
- env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
- ch := (*(*chan<- discovery.Advertisement)(jutil.NativePtr(goPtr)))
-
- jAdv := jutil.Object(uintptr(unsafe.Pointer(jAdvObj)))
- var adv discovery.Advertisement
- if err := jutil.GoVomCopy(env, jAdv, jAdvertisementClass, &adv); err != nil {
- jutil.JThrowV(env, err)
- return
- }
- ch <- adv
-}
-
-//export Java_io_v_android_libs_discovery_ble_NativeScanHandler_nativeFinalize
-func Java_io_v_android_libs_discovery_ble_NativeScanHandler_nativeFinalize(jenv *C.JNIEnv, _ C.jobject, goPtr C.jlong) {
- jutil.GoUnref(jutil.NativePtr(goPtr))
-}
diff --git a/libs/discovery/plugin.go b/libs/discovery/plugin.go
deleted file mode 100644
index 22f7fbb..0000000
--- a/libs/discovery/plugin.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2015 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 discovery
-
-import (
- "runtime"
-
- "v.io/v23/context"
-
- "v.io/x/ref/lib/discovery"
-
- jutil "v.io/x/jni/util"
- jcontext "v.io/x/jni/v23/context"
-)
-
-// #include "jni.h"
-import "C"
-
-func NewBleCreator(env jutil.Env, context jutil.Object) func(string) (discovery.Plugin, error) {
- // Reference Android Context; it will be de-referenced when the plugin
- // created below is garbage-collected (through the finalizer callback we
- // setup in the function below). This function should only be executed once.
- jContext := jutil.NewGlobalRef(env, context)
- return func(host string) (discovery.Plugin, error) {
- env, freeFunc := jutil.GetEnv()
- defer freeFunc()
- jPlugin, err := jutil.NewObject(env, jBlePluginClass, []jutil.Sign{androidContextSign}, jContext)
-
- jutil.DeleteGlobalRef(env, jContext)
- if err != nil {
- return nil, err
- }
- // Reference Android BlePlugin; it will be de-referenced when the plugin
- // created below is garbage-collected (through the finalizer callback we
- // setup below).
- jPlugin = jutil.NewGlobalRef(env, jPlugin)
- p := &plugin{
- trigger: discovery.NewTrigger(),
- jPlugin: jPlugin,
- }
- runtime.SetFinalizer(p, func(p *plugin) {
- env, freeFunc := jutil.GetEnv()
- defer freeFunc()
- jutil.DeleteGlobalRef(env, p.jPlugin)
- })
- return p, nil
- }
-
-}
-
-type plugin struct {
- trigger *discovery.Trigger
- jPlugin jutil.Object
-}
-
-func (p *plugin) Advertise(ctx *context.T, ad discovery.Advertisement, done func()) error {
- env, freeFunc := jutil.GetEnv()
- defer freeFunc()
- jContext, err := jcontext.JavaContext(env, ctx, nil)
- if err != nil {
- return err
- }
- jAdv, err := jutil.JVomCopy(env, ad, jAdvertisementClass)
- if err != nil {
- return err
- }
-
- err = jutil.CallVoidMethod(env, p.jPlugin, "addAdvertisement", []jutil.Sign{contextSign, advertisementSign}, jContext, jAdv)
-
- p.trigger.Add(done, ctx.Done())
-
- return err
-}
-
-func (p *plugin) Scan(ctx *context.T, interfaceName string, ch chan<- discovery.Advertisement, done func()) error {
- env, freeFunc := jutil.GetEnv()
- defer freeFunc()
- jContext, err := jcontext.JavaContext(env, ctx, nil)
- if err != nil {
- return err
- }
-
- jutil.GoRef(&ch)
- jNativeScanHandler, err := jutil.NewObject(env, jNativeScanHandlerClass, []jutil.Sign{jutil.LongSign}, int64(jutil.PtrValue(&ch)))
- if err != nil {
- return err
- }
-
- err = jutil.CallVoidMethod(env, p.jPlugin, "addScanner", []jutil.Sign{contextSign, jutil.StringSign, scanHandlerSign}, jContext, interfaceName, jNativeScanHandler)
- if err != nil {
- return err
- }
- p.trigger.Add(done, ctx.Done())
- return nil
-}