make broadcast recipients explicit

This commit is contained in:
geeksville
2020-01-26 11:33:51 -08:00
parent a306c4466d
commit ff281b6c39
4 changed files with 46 additions and 7 deletions

View File

@@ -2,7 +2,7 @@
* use android service from Signal
* DONE handle failures in onCharWrite, instead of logAssert - because they can happen if device goes away
* explictly broadcast towards signal https://developer.android.com/guide/components/broadcasts
* DONE explictly broadcast towards signal https://developer.android.com/guide/components/broadcasts
* make test implementation of android service (doesn't use bluetooth)
* clean up sw update code in device side
* DONE add broadcasters for use by signal (node changes and packet received)
@@ -10,7 +10,7 @@
* add real messaging code/protobufs
* use https://codelabs.developers.google.com/codelabs/jetpack-compose-basics/#4 to show service state
* connect to bluetooth device automatically using minimum power
* have signal declare receivers: https://developer.android.com/guide/components/broadcasts#manifest-declared-receivers
* DONE have signal declare receivers: https://developer.android.com/guide/components/broadcasts#manifest-declared-receivers
* fix BT device scanning
* call crashlytics from exceptionReporter!!! currently not logging failures caught there

View File

@@ -7,6 +7,9 @@ package com.geeksville.mesh;
* Note - these calls might throw RemoteException to indicate mesh error states
*/
interface IMeshService {
/// Tell the service where to send its broadcasts of received packets
void subscribeReceiver(String packageName, String receiverName);
/**
* Set the ID info for this node

View File

@@ -157,7 +157,7 @@ class MainActivity : AppCompatActivity(), Logging {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
val m = IMeshService.Stub.asInterface(service)
meshService = m
// Do some test operations
m.setOwner("+16508675309", "Kevin Xter", "kx")
val testPayload = "hello world".toByteArray()

View File

@@ -1,10 +1,13 @@
package com.geeksville.mesh
import android.app.Activity
import android.app.ActivityManager
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Binder
import android.os.IBinder
import com.geeksville.android.Logging
import com.geeksville.mesh.MeshProtos.MeshPacket
@@ -14,6 +17,7 @@ import com.geeksville.util.toRemoteExceptions
import com.google.protobuf.ByteString
import java.nio.charset.Charset
/**
* Handles all the communication with android apps. Also keeps an internal model
* of the network state.
@@ -35,6 +39,10 @@ class MeshService : Service(), Logging {
private const val NODE_NUM_NO_MESH = -1
}
/// A mapping of receiver class name to package name - used for explicit broadcasts
private val clientPackages = mutableMapOf<String, String>()
/*
see com.geeksville.mesh broadcast intents
// RECEIVED_OPAQUE for data received from other nodes
@@ -42,6 +50,13 @@ class MeshService : Service(), Logging {
// CONNECTION_CHANGED for losing/gaining connection to the packet radio
*/
private fun explicitBroadcast(intent: Intent) {
clientPackages.forEach {
intent.setClassName(it.value, it.key)
sendBroadcast(intent)
}
}
/**
* The RECEIVED_OPAQUE:
* Payload will be the raw bytes which were contained within a MeshPacket.Opaque field
@@ -53,14 +68,14 @@ class MeshService : Service(), Logging {
intent.putExtra(EXTRA_SENDER, senderId)
intent.putExtra(EXTRA_PAYLOAD, payload)
intent.putExtra(EXTRA_TYP, typ)
sendBroadcast(intent)
explicitBroadcast(intent)
}
private fun broadcastNodeChange(nodeId: String, isOnline: Boolean) {
val intent = Intent("$prefix.NODE_CHANGE")
intent.putExtra(EXTRA_ID, nodeId)
intent.putExtra(EXTRA_ONLINE, isOnline)
sendBroadcast(intent)
explicitBroadcast(intent)
}
/// Send a command/packet to our radio
@@ -68,8 +83,25 @@ class MeshService : Service(), Logging {
RadioInterfaceService.sendToRadio(this, p.build().toByteArray())
}
override fun onBind(intent: Intent): IBinder {
// Return the interface
/**
* We track everyone who has bound to us, so when we can explicitly broadcast to them
* per new restrictions in android api 26 https://developer.android.com/guide/components/broadcasts#receiving-broadcasts
*/
private fun recordNewClient() {
val pid = Binder.getCallingPid()
val activityManager = getSystemService(Activity.ACTIVITY_SERVICE) as ActivityManager
val procs = activityManager.runningAppProcesses.filter {
it.pid == pid
}
val packages = procs.flatMap {
it.pkgList.asList()
}
clientPackages.addAll(packages)
}
override fun onBind(intent: Intent?): IBinder? {
return binder
}
@@ -289,6 +321,10 @@ class MeshService : Service(), Logging {
private val binder = object : IMeshService.Stub() {
// Note: bound methods don't get properly exception caught/logged, so do that with a wrapper
// per https://blog.classycode.com/dealing-with-exceptions-in-aidl-9ba904c6d63
override fun subscribeReceiver(packageName: String, receiverName: String) =
toRemoteExceptions {
clientPackages[receiverName] = packageName
}
override fun setOwner(myId: String, longName: String, shortName: String) =
toRemoteExceptions {