Set AETHERFORGE env vars in APK wrapper before agent spawn.
Java AgentProcess passes SERVER_URL, WORKER_NUMBER, PLATFORM=android, and Wi-Fi/battery/foreground-service probes to the embedded Go worker.
This commit is contained in:
@@ -5,6 +5,7 @@ import org.json.JSONObject
|
|||||||
|
|
||||||
data class AgentConfig(
|
data class AgentConfig(
|
||||||
val workerName: String,
|
val workerName: String,
|
||||||
|
val workerNumber: String,
|
||||||
val serverUrl: String,
|
val serverUrl: String,
|
||||||
val fleetSecret: String?,
|
val fleetSecret: String?,
|
||||||
val miningEnabled: Boolean,
|
val miningEnabled: Boolean,
|
||||||
@@ -19,6 +20,9 @@ data class AgentConfig(
|
|||||||
val json = assetJson?.let { JSONObject(it) }
|
val json = assetJson?.let { JSONObject(it) }
|
||||||
val worker = intentExtras["worker_name"]
|
val worker = intentExtras["worker_name"]
|
||||||
?: json?.optString("worker_name").orEmpty()
|
?: json?.optString("worker_name").orEmpty()
|
||||||
|
val workerNumber = intentExtras["worker_number"]
|
||||||
|
?: json?.optString("worker_number")
|
||||||
|
?: worker
|
||||||
val server = intentExtras["server_url"]
|
val server = intentExtras["server_url"]
|
||||||
?: json?.optString("server_url").orEmpty()
|
?: json?.optString("server_url").orEmpty()
|
||||||
val secret = intentExtras["fleet_secret"]
|
val secret = intentExtras["fleet_secret"]
|
||||||
@@ -28,6 +32,7 @@ data class AgentConfig(
|
|||||||
|
|
||||||
return AgentConfig(
|
return AgentConfig(
|
||||||
workerName = worker.ifBlank { "android-fleet-node" },
|
workerName = worker.ifBlank { "android-fleet-node" },
|
||||||
|
workerNumber = workerNumber.ifBlank { worker.ifBlank { "android-fleet-node" } },
|
||||||
serverUrl = server.ifBlank { "http://127.0.0.1:8989" },
|
serverUrl = server.ifBlank { "http://127.0.0.1:8989" },
|
||||||
fleetSecret = secret,
|
fleetSecret = secret,
|
||||||
miningEnabled = mining,
|
miningEnabled = mining,
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
package com.aetherforge.agent
|
package com.aetherforge.agent
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
import android.os.BatteryManager
|
||||||
|
import android.os.Build
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object AgentProcess {
|
object AgentProcess {
|
||||||
@@ -8,14 +13,24 @@ object AgentProcess {
|
|||||||
@Volatile
|
@Volatile
|
||||||
private var process: Process? = null
|
private var process: Process? = null
|
||||||
|
|
||||||
fun start(binary: File, filesDir: File, config: AgentConfig) {
|
fun start(
|
||||||
|
binary: File,
|
||||||
|
filesDir: File,
|
||||||
|
config: AgentConfig,
|
||||||
|
probeEnv: Map<String, String> = emptyMap(),
|
||||||
|
) {
|
||||||
stop()
|
stop()
|
||||||
val env = hashMapOf(
|
val env = hashMapOf(
|
||||||
"HOME" to filesDir.absolutePath,
|
"HOME" to filesDir.absolutePath,
|
||||||
"TMPDIR" to filesDir.absolutePath,
|
"TMPDIR" to filesDir.absolutePath,
|
||||||
"AETHERFORGE_MINER_EXECUTION" to "inprocess",
|
"AETHERFORGE_MINER_EXECUTION" to "inprocess",
|
||||||
|
"AETHERFORGE_SERVER_URL" to config.serverUrl,
|
||||||
|
"AETHERFORGE_WORKER_NUMBER" to config.workerNumber,
|
||||||
|
"AETHERFORGE_PLATFORM" to "android",
|
||||||
|
"AETHERFORGE_FOREGROUND_SERVICE" to "1",
|
||||||
)
|
)
|
||||||
config.fleetSecret?.let { env["AETHERFORGE_FLEET_SECRET"] = it }
|
config.fleetSecret?.let { env["AETHERFORGE_FLEET_SECRET"] = it }
|
||||||
|
env.putAll(probeEnv)
|
||||||
|
|
||||||
val cmd = listOf(binary.absolutePath, "--run")
|
val cmd = listOf(binary.absolutePath, "--run")
|
||||||
Log.i(TAG, "spawning agent: ${cmd.joinToString(" ")}")
|
Log.i(TAG, "spawning agent: ${cmd.joinToString(" ")}")
|
||||||
@@ -39,6 +54,30 @@ object AgentProcess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun probeEnvironment(context: Context): Map<String, String> {
|
||||||
|
val wifi = runCatching {
|
||||||
|
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
val network = cm.activeNetwork ?: return@runCatching false
|
||||||
|
val caps = cm.getNetworkCapabilities(network) ?: return@runCatching false
|
||||||
|
caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
|
}.getOrDefault(false)
|
||||||
|
|
||||||
|
val batteryOk = runCatching {
|
||||||
|
val bm = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
val level = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
|
||||||
|
level >= 15
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}.getOrDefault(true)
|
||||||
|
|
||||||
|
return mapOf(
|
||||||
|
"AETHERFORGE_WIFI_CONNECTED" to if (wifi) "1" else "0",
|
||||||
|
"AETHERFORGE_BATTERY_OK" to if (batteryOk) "1" else "0",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun stop() {
|
fun stop() {
|
||||||
process?.let {
|
process?.let {
|
||||||
runCatching { it.destroy() }
|
runCatching { it.destroy() }
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class AgentService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!AgentProcess.isAlive()) {
|
if (!AgentProcess.isAlive()) {
|
||||||
AgentProcess.start(binary, filesDir, config)
|
AgentProcess.start(binary, filesDir, config, AgentProcess.probeEnvironment(this))
|
||||||
}
|
}
|
||||||
return START_STICKY
|
return START_STICKY
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
{
|
{
|
||||||
"build_id": "android-dev",
|
"server_url": "http://192.168.1.10:8989",
|
||||||
"fleet_secret_set": false,
|
"worker_name": "tablet-1"
|
||||||
"mining": {
|
}
|
||||||
"enabled": false,
|
|
||||||
"mode": "idle",
|
|
||||||
"note": "CPU mining disabled by default; enable via server policy or re-forge."
|
|
||||||
},
|
|
||||||
"server_url": "http://test:8989",
|
|
||||||
"worker_name": "test-node"
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,7 @@ import org.json.JSONObject
|
|||||||
|
|
||||||
data class AgentConfig(
|
data class AgentConfig(
|
||||||
val workerName: String,
|
val workerName: String,
|
||||||
|
val workerNumber: String,
|
||||||
val serverUrl: String,
|
val serverUrl: String,
|
||||||
val fleetSecret: String?,
|
val fleetSecret: String?,
|
||||||
val miningEnabled: Boolean,
|
val miningEnabled: Boolean,
|
||||||
@@ -19,6 +20,9 @@ data class AgentConfig(
|
|||||||
val json = assetJson?.let { JSONObject(it) }
|
val json = assetJson?.let { JSONObject(it) }
|
||||||
val worker = intentExtras["worker_name"]
|
val worker = intentExtras["worker_name"]
|
||||||
?: json?.optString("worker_name").orEmpty()
|
?: json?.optString("worker_name").orEmpty()
|
||||||
|
val workerNumber = intentExtras["worker_number"]
|
||||||
|
?: json?.optString("worker_number")
|
||||||
|
?: worker
|
||||||
val server = intentExtras["server_url"]
|
val server = intentExtras["server_url"]
|
||||||
?: json?.optString("server_url").orEmpty()
|
?: json?.optString("server_url").orEmpty()
|
||||||
val secret = intentExtras["fleet_secret"]
|
val secret = intentExtras["fleet_secret"]
|
||||||
@@ -28,6 +32,7 @@ data class AgentConfig(
|
|||||||
|
|
||||||
return AgentConfig(
|
return AgentConfig(
|
||||||
workerName = worker.ifBlank { "android-fleet-node" },
|
workerName = worker.ifBlank { "android-fleet-node" },
|
||||||
|
workerNumber = workerNumber.ifBlank { worker.ifBlank { "android-fleet-node" } },
|
||||||
serverUrl = server.ifBlank { "http://127.0.0.1:8989" },
|
serverUrl = server.ifBlank { "http://127.0.0.1:8989" },
|
||||||
fleetSecret = secret,
|
fleetSecret = secret,
|
||||||
miningEnabled = mining,
|
miningEnabled = mining,
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
package com.aetherforge.agent
|
package com.aetherforge.agent
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
import android.os.BatteryManager
|
||||||
|
import android.os.Build
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object AgentProcess {
|
object AgentProcess {
|
||||||
@@ -8,14 +13,24 @@ object AgentProcess {
|
|||||||
@Volatile
|
@Volatile
|
||||||
private var process: Process? = null
|
private var process: Process? = null
|
||||||
|
|
||||||
fun start(binary: File, filesDir: File, config: AgentConfig) {
|
fun start(
|
||||||
|
binary: File,
|
||||||
|
filesDir: File,
|
||||||
|
config: AgentConfig,
|
||||||
|
probeEnv: Map<String, String> = emptyMap(),
|
||||||
|
) {
|
||||||
stop()
|
stop()
|
||||||
val env = hashMapOf(
|
val env = hashMapOf(
|
||||||
"HOME" to filesDir.absolutePath,
|
"HOME" to filesDir.absolutePath,
|
||||||
"TMPDIR" to filesDir.absolutePath,
|
"TMPDIR" to filesDir.absolutePath,
|
||||||
"AETHERFORGE_MINER_EXECUTION" to "inprocess",
|
"AETHERFORGE_MINER_EXECUTION" to "inprocess",
|
||||||
|
"AETHERFORGE_SERVER_URL" to config.serverUrl,
|
||||||
|
"AETHERFORGE_WORKER_NUMBER" to config.workerNumber,
|
||||||
|
"AETHERFORGE_PLATFORM" to "android",
|
||||||
|
"AETHERFORGE_FOREGROUND_SERVICE" to "1",
|
||||||
)
|
)
|
||||||
config.fleetSecret?.let { env["AETHERFORGE_FLEET_SECRET"] = it }
|
config.fleetSecret?.let { env["AETHERFORGE_FLEET_SECRET"] = it }
|
||||||
|
env.putAll(probeEnv)
|
||||||
|
|
||||||
val cmd = listOf(binary.absolutePath, "--run")
|
val cmd = listOf(binary.absolutePath, "--run")
|
||||||
Log.i(TAG, "spawning agent: ${cmd.joinToString(" ")}")
|
Log.i(TAG, "spawning agent: ${cmd.joinToString(" ")}")
|
||||||
@@ -39,6 +54,30 @@ object AgentProcess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun probeEnvironment(context: Context): Map<String, String> {
|
||||||
|
val wifi = runCatching {
|
||||||
|
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
val network = cm.activeNetwork ?: return@runCatching false
|
||||||
|
val caps = cm.getNetworkCapabilities(network) ?: return@runCatching false
|
||||||
|
caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
|
}.getOrDefault(false)
|
||||||
|
|
||||||
|
val batteryOk = runCatching {
|
||||||
|
val bm = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
val level = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
|
||||||
|
level >= 15
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}.getOrDefault(true)
|
||||||
|
|
||||||
|
return mapOf(
|
||||||
|
"AETHERFORGE_WIFI_CONNECTED" to if (wifi) "1" else "0",
|
||||||
|
"AETHERFORGE_BATTERY_OK" to if (batteryOk) "1" else "0",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun stop() {
|
fun stop() {
|
||||||
process?.let {
|
process?.let {
|
||||||
runCatching { it.destroy() }
|
runCatching { it.destroy() }
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class AgentService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!AgentProcess.isAlive()) {
|
if (!AgentProcess.isAlive()) {
|
||||||
AgentProcess.start(binary, filesDir, config)
|
AgentProcess.start(binary, filesDir, config, AgentProcess.probeEnvironment(this))
|
||||||
}
|
}
|
||||||
return START_STICKY
|
return START_STICKY
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user