Skip to content

Commit 6f447c8

Browse files
jamesarichCopilot
andcommitted
refactor: remove AIDL API and modernize radio architecture
Remove the deprecated AIDL/IPC API surface and perform deep architectural modernization of the radio command pipeline, aligning with the meshtastic-sdk AdminApiImpl pattern for future SDK migration. Key changes: 1. AIDL Removal & Infrastructure Cleanup - Delete core:api module and all AIDL interfaces - Remove ServiceBroadcasts + CommonParcelable infrastructure - Remove core:api from CI workflow lint/publish steps 2. Model Modernization - Introduce NodeAddress sealed class with type-safe addressing - Remove deprecated DataPacket constants in favor of NodeAddress - Consolidate dual node maps into single source with getNodeById - Split large model files, deduplicate NodeEntity, flatten RadioController 3. Service Layer Refactoring (SDK-aligned) - Remove ServiceAction sealed class, use direct suspend calls - Convert CommandSender & MeshActionHandler to suspend APIs - Merge MeshActionHandler into DirectRadioControllerImpl (ViewModel → RadioController → CommandSender, no intermediate layer) - Build AdminMessage protos directly with typed protos end-to-end - Apply structured concurrency to NodeRequestActions/NodeManagementActions - Fix CancellationException handling throughout Architecture (before → after): ViewModel → RadioController → Handler → CommandSender → PacketHandler ViewModel → RadioController → CommandSender → PacketHandler Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent e167b58 commit 6f447c8

150 files changed

Lines changed: 1296 additions & 4652 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ Each module has its own README with details on its responsibilities, API surface
8787

8888
| Module | Description |
8989
|---|---|
90-
| [core/api](core/api/README.md) | AIDL service API for third-party integrations |
9190
| [core/domain](core/domain/README.md) | Business-logic use cases (radio config, sessions, exports) |
9291
| [core/repository](core/repository/README.md) | Data & infrastructure contracts (RadioTransport, NodeRepository, ServiceRepository) |
9392
| [core/takserver](core/takserver/README.md) | Meshtastic ↔ TAK (ATAK/iTAK) bridge — CoT server & conversion |
@@ -123,13 +122,9 @@ Each module has its own README with details on its responsibilities, API surface
123122

124123
You can help translate the app into your native language using [Crowdin](https://crowdin.meshtastic.org/android).
125124

126-
## API & Integration
125+
## Integration
127126

128-
Developers can integrate with the Meshtastic Android app using our published API library via **JitPack**. This allows third-party applications (like the ATAK plugin) to communicate with the mesh service via AIDL.
129-
130-
For detailed integration instructions, see [core/api/README.md](core/api/README.md).
131-
132-
Additionally, the app includes a built-in **Local TAK Server** feature that can be enabled in settings. This runs a local TCP server on port 8089 to allow ATAK clients to connect directly and route their traffic over the mesh.
127+
The app includes a built-in **Local TAK Server** feature that can be enabled in settings. This runs a local TCP server on port 8089 to allow ATAK clients to connect directly and route their traffic over the mesh.
133128

134129
## Building the Android App
135130
> [!WARNING]

androidApp/src/fdroid/kotlin/org/meshtastic/app/map/MapView.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ import org.meshtastic.core.common.util.nowMillis
8787
import org.meshtastic.core.common.util.nowSeconds
8888
import org.meshtastic.core.model.DataPacket
8989
import org.meshtastic.core.model.Node
90+
import org.meshtastic.core.model.NodeAddress
9091
import org.meshtastic.core.resources.Res
9192
import org.meshtastic.core.resources.calculating
9293
import org.meshtastic.core.resources.cancel
@@ -433,7 +434,7 @@ fun MapView(
433434
}
434435
}
435436

436-
fun getUsername(id: String?) = if (id == DataPacket.ID_LOCAL || (myId != null && id == myId)) {
437+
fun getUsername(id: String?) = if (id == NodeAddress.ID_LOCAL || (myId != null && id == myId)) {
437438
getString(Res.string.you)
438439
} else {
439440
mapViewModel.getUser(id).long_name

androidApp/src/google/kotlin/org/meshtastic/app/map/MapViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import org.meshtastic.app.map.model.CustomTileProviderConfig
5050
import org.meshtastic.app.map.prefs.map.GoogleMapsPrefs
5151
import org.meshtastic.app.map.repository.CustomTileProviderRepository
5252
import org.meshtastic.core.di.CoroutineDispatchers
53+
import org.meshtastic.core.model.NodeAddress
5354
import org.meshtastic.core.model.RadioController
5455
import org.meshtastic.core.repository.MapPrefs
5556
import org.meshtastic.core.repository.NodeRepository
@@ -670,8 +671,7 @@ class MapViewModel(
670671
(currentTileProvider as? MBTilesProvider)?.close()
671672
}
672673

673-
override fun getUser(userId: String?) =
674-
nodeRepository.getUser(userId ?: org.meshtastic.core.model.DataPacket.ID_BROADCAST)
674+
override fun getUser(userId: String?) = nodeRepository.getUser(userId ?: NodeAddress.ID_BROADCAST)
675675
}
676676

677677
enum class LayerType {

androidApp/src/main/AndroidManifest.xml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,12 @@
161161
android:name="google_analytics_default_allow_analytics_storage"
162162
android:value="false" />
163163

164-
<!-- This is the public API for doing mesh radio operations from android apps -->
164+
<!-- In-app mesh foreground service -->
165165
<service
166166
android:name="org.meshtastic.core.service.MeshService"
167167
android:enabled="true"
168168
android:foregroundServiceType="connectedDevice|location"
169-
android:exported="true" tools:ignore="ExportedActivity">
170-
<intent-filter>
171-
<action android:name="com.geeksville.mesh.Service" />
172-
</intent-filter>
173-
</service>
169+
android:exported="false" />
174170

175171
<service
176172
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
@@ -272,7 +268,7 @@
272268
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
273269

274270
<!-- for testing -->
275-
<action android:name="com.geeksville.mesh.SIM_BOOT" />
271+
<action android:name="org.meshtastic.app.SIM_BOOT" />
276272
</intent-filter>
277273

278274
<!-- Also restart our service if the app gets upgraded -->

androidApp/src/main/kotlin/org/meshtastic/app/MainActivity.kt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ import org.meshtastic.core.network.repository.UsbRepository
6363
import org.meshtastic.core.nfc.NfcScannerEffect
6464
import org.meshtastic.core.resources.Res
6565
import org.meshtastic.core.resources.channel_invalid
66-
import org.meshtastic.core.service.MeshServiceClient
66+
import org.meshtastic.core.service.MeshService
67+
import org.meshtastic.core.service.startService
6768
import org.meshtastic.core.ui.theme.AppTheme
6869
import org.meshtastic.core.ui.theme.MODE_DYNAMIC
6970
import org.meshtastic.core.ui.util.LocalAnalyticsIntroProvider
@@ -95,18 +96,9 @@ class MainActivity : AppCompatActivity() {
9596

9697
private val usbRepository: UsbRepository by inject()
9798

98-
/**
99-
* Activity-lifecycle-aware client that binds to the mesh service. Note: This is used implicitly as it registers
100-
* itself as a LifecycleObserver in its init block.
101-
*/
102-
internal val meshServiceClient: MeshServiceClient by inject { parametersOf(this) }
103-
10499
override fun onCreate(savedInstanceState: Bundle?) {
105100
installSplashScreen()
106101

107-
// Eagerly evaluate lazy Koin dependency so it registers its LifecycleObserver
108-
meshServiceClient.hashCode()
109-
110102
super.onCreate(savedInstanceState)
111103

112104
enableEdgeToEdge()
@@ -168,6 +160,11 @@ class MainActivity : AppCompatActivity() {
168160
handleIntent(intent)
169161
}
170162

163+
override fun onStart() {
164+
super.onStart()
165+
MeshService.startService(this)
166+
}
167+
171168
override fun onResume() {
172169
super.onResume()
173170
// Belt-and-suspenders for the Android 12+ attach-intent quirk: if the activity is

build-logic/convention/src/main/kotlin/RootConventionPlugin.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ private val DEVICE_TEST_MODULES = listOf(":core:database", ":core:model")
8181
private val ALL_MODULES_FULL =
8282
listOf(
8383
":androidApp",
84-
":core:api",
8584
":core:barcode",
8685
":core:ble",
8786
":core:common",
@@ -115,7 +114,7 @@ private val ALL_MODULES_FULL =
115114
)
116115

117116
/** Android-only modules that don't apply the KMP plugin. */
118-
private val ANDROID_ONLY_MODULES = setOf(":androidApp", ":core:api", ":core:barcode", ":feature:widget")
117+
private val ANDROID_ONLY_MODULES = setOf(":androidApp", ":core:barcode", ":feature:widget")
119118

120119
/**
121120
* Modules excluded from Dokka aggregation. :core:proto contains only auto-generated Wire classes (no KDoc value) and
@@ -128,6 +127,6 @@ private fun allModules(): List<String> = ALL_MODULES_FULL
128127

129128
/**
130129
* Modules that apply the KMP plugin and should be compiled for JVM + iOS targets. Excludes pure-Android modules
131-
* (:androidApp, :core:api, :core:barcode, :feature:widget) and the desktop JVM-only module.
130+
* (:androidApp, :core:barcode, :feature:widget) and the desktop JVM-only module.
132131
*/
133132
private fun kmpModules(): List<String> = allModules().filter { it !in ANDROID_ONLY_MODULES + ":desktopApp" }

codecov.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ component_management:
6161
ignore:
6262
- "**/build/**"
6363
- "**/*.pb.kt" # Generated Protobuf code
64-
- "**/*.aidl" # AIDL interface files
65-
- "**/aidl/**" # Generated AIDL code
6664
- "core/resources/**" # Centralized resources
6765
- "**/test/**" # Unit tests
6866
- "**/androidTest/**" # Instrumented tests

core/api/README.md

Lines changed: 0 additions & 79 deletions
This file was deleted.

core/api/build.gradle.kts

Lines changed: 0 additions & 52 deletions
This file was deleted.

core/api/src/main/AndroidManifest.xml

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)