Skip to content

Commit 0149d39

Browse files
malysclaude
andcommitted
feat(catalog): one Call action taking a number or a contact
CALL_NUMBER now carries a CONTACT value, so a single catalogue entry accepts either a typed number or a name from the phone book. Two entries for one capability made the picker ask a question the user should not have to answer before knowing what they wanted to dial. CALL_CONTACT is deprecated and dropped from byGroup() rather than deleted: enum entries are persisted by name, so removing it would deserialise to null in every rule that already uses it — the crash class this catalogue has hit before. It stays loadable and executable, and simply stops being offered. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent d74b041 commit 0149d39

10 files changed

Lines changed: 43 additions & 14 deletions

File tree

‎AGENTS.md‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
Shared vehicle-access library for the SAIC MG4 (AAOS 9, MT2712), consumed by MG4Control,
44
MG4Tasker and MG4ABRPUploader via git submodule + Gradle subproject.
55

6+
MG4Hardware is the shared vehicle layer for **MG4Suite**. The workspace `AGENTS.md` and
7+
normative workspace `DESIGN.md` apply; this file defines library-specific invariants.
8+
69
Commit author: malys.training@gmail.com
710

811
## Why this exists
@@ -13,11 +16,10 @@ The apps are thin; the vehicle lives here.
1316

1417
## Non-negotiables
1518

16-
- **The 0 km/h gate is here.** `VehicleWriteGate` refuses road-behaviour writes above
17-
0 km/h and fails closed on unreadable speed, inside the low-level write primitives. Every
18-
gated setter carries `@RequiresStandstill`; `RequiresStandstillTest`-style coverage keeps
19-
the set honest. Comfort writes are not gated. Park rescues the unreadable-speed refusal
20-
and nothing else — it must never override a speed that did read.
19+
- **The 0 km/h gate is here.** `VehicleWriteGate` permits a vehicle-setting write only when
20+
speed is readable and exactly 0 km/h, inside the low-level write primitives. Every setter
21+
carries `@RequiresStandstill`; coverage keeps the set honest. Unknown/negative speed
22+
fails closed, and park state does not override that refusal.
2123
- **Per-firmware routing, never universal.** SWI68/69/131/132/133/165 differ; dispatch
2224
through `FirmwareInfo`. Any new vehicle call must branch per generation.
2325
- **Unreadable ≠ a value.** Getters return null / -1 when the layer is not ready or the

‎CHANGELOG.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ All notable changes to this project are documented here. Format follows
44
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
55
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [Unreleased]
8+
9+
### Changed
10+
11+
- **One "Call" action.** `CALL_NUMBER` now carries a `CONTACT` value, so the same entry takes
12+
either a typed number or a name from the phone book. `CALL_CONTACT` is deprecated and no
13+
longer offered by `ActionType.byGroup()`: it stays in the enum only so rules saved by a
14+
release that exposed it still load and still call, since enum entries are persisted by name
15+
and a removed one deserialises to null.
16+
717
## [0.2.0] - 2026-08-02
818

919
### Added

‎lib/src/main/java/com/mg4/hardware/catalog/ActionType.kt‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -452,16 +452,22 @@ enum class ActionType(
452452
@SupportedOn(SWI68, SWI165)
453453
CALL_NUMBER(
454454
R.string.act_call, ActionGroup.SYSTEM,
455-
ValueSpec(ValueKind.TEXT), "CALL_NUMBER"
455+
ValueSpec(ValueKind.CONTACT), "CALL_NUMBER"
456456
),
457-
/** Selects from the PBAP-synchronised Android phone book, then calls the stored number. */
457+
/**
458+
* Kept only so rules saved by releases that exposed a separate contact action still load.
459+
* New rules use [CALL_NUMBER], whose editor accepts either a number or a contact.
460+
*/
461+
@Deprecated("Compatibility alias for saved rules; use CALL_NUMBER")
458462
@SupportedOn(SWI68, SWI165)
459463
CALL_CONTACT(
460464
R.string.act_call_contact, ActionGroup.SYSTEM,
461465
ValueSpec(ValueKind.CONTACT), "CALL_CONTACT"
462466
);
463467

464468
companion object {
465-
fun byGroup(): Map<ActionGroup, List<ActionType>> = entries.groupBy { it.group }
469+
@Suppress("DEPRECATION")
470+
fun byGroup(): Map<ActionGroup, List<ActionType>> =
471+
entries.filterNot { it == CALL_CONTACT }.groupBy { it.group }
466472
}
467473
}

‎lib/src/main/res/values-de/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
<string name="act_tune_radio">Radiosender einstellen</string>
137137
<string name="value_radio_hint">z. B. 103.5 oder AM 1080</string>
138138
<string name="act_navigate">Navigieren zu</string>
139-
<string name="act_call">Nummer anrufen</string>
139+
<string name="act_call">Anrufen</string>
140140
<string name="act_call_contact">Kontakt anrufen</string>
141141
<string name="cond_window_position">Fensteröffnung</string>
142142
<string name="cond_doors_locked">Türen verriegelt</string>

‎lib/src/main/res/values-es/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
<string name="act_tune_radio">Sintonizar la radio</string>
137137
<string name="value_radio_hint">p. ej. 103.5 o AM 1080</string>
138138
<string name="act_navigate">Navegar hasta</string>
139-
<string name="act_call">Llamar a un número</string>
139+
<string name="act_call">Llamar</string>
140140
<string name="act_call_contact">Llamar a un contacto</string>
141141
<string name="cond_window_position">Apertura de ventanillas</string>
142142
<string name="cond_doors_locked">Puertas bloqueadas</string>

‎lib/src/main/res/values-fr/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@
157157
<string name="act_navigate">Naviguer vers</string>
158158
<string name="act_webhook_get">Appeler un webhook (GET)</string>
159159
<string name="act_webhook_post">Appeler un webhook (POST)</string>
160-
<string name="act_call">Appeler un numéro</string>
160+
<string name="act_call">Appeler</string>
161161
<string name="act_call_contact">Appeler un contact</string>
162162
<string name="cond_window_position">Ouverture des vitres</string>
163163
<string name="cond_doors_locked">Portes verrouillées</string>

‎lib/src/main/res/values-it/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
<string name="act_tune_radio">Sintonizza la radio</string>
137137
<string name="value_radio_hint">es. 103.5 o AM 1080</string>
138138
<string name="act_navigate">Naviga verso</string>
139-
<string name="act_call">Chiama un numero</string>
139+
<string name="act_call">Chiama</string>
140140
<string name="act_call_contact">Chiama un contatto</string>
141141
<string name="cond_window_position">Apertura finestrini</string>
142142
<string name="cond_doors_locked">Porte bloccate</string>

‎lib/src/main/res/values-pt/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
<string name="act_tune_radio">Sintonizar o rádio</string>
137137
<string name="value_radio_hint">ex. 103.5 ou AM 1080</string>
138138
<string name="act_navigate">Navegar para</string>
139-
<string name="act_call">Ligar para um número</string>
139+
<string name="act_call">Ligar</string>
140140
<string name="act_call_contact">Ligar para um contacto</string>
141141
<string name="cond_window_position">Abertura dos vidros</string>
142142
<string name="cond_doors_locked">Portas trancadas</string>

‎lib/src/main/res/values/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@
157157
<string name="act_navigate">Navigate to</string>
158158
<string name="act_webhook_get">Call webhook (GET)</string>
159159
<string name="act_webhook_post">Call webhook (POST)</string>
160-
<string name="act_call">Call a number</string>
160+
<string name="act_call">Call</string>
161161
<string name="act_call_contact">Call a contact</string>
162162
<string name="cond_window_position">Window opening</string>
163163
<string name="cond_doors_locked">Doors locked</string>

‎lib/src/test/java/com/mg4/hardware/catalog/CatalogConsistencyTest.kt‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.mg4.hardware.catalog.ActionType
44
import com.mg4.hardware.catalog.ConditionType
55
import com.mg4.hardware.catalog.ValueKind
66
import org.junit.Assert.assertFalse
7+
import org.junit.Assert.assertEquals
78
import org.junit.Assert.assertNotNull
89
import org.junit.Assert.assertTrue
910
import org.junit.Test
@@ -15,6 +16,16 @@ import org.junit.Test
1516
*/
1617
class CatalogConsistencyTest {
1718

19+
@Suppress("DEPRECATION")
20+
@Test
21+
fun `call is one public action accepting numbers or contacts`() {
22+
val publicActions = ActionType.byGroup().values.flatten()
23+
24+
assertEquals(ValueKind.CONTACT, ActionType.CALL_NUMBER.spec.kind)
25+
assertTrue(ActionType.CALL_NUMBER in publicActions)
26+
assertFalse(ActionType.CALL_CONTACT in publicActions)
27+
}
28+
1829
@Test
1930
fun `toute action vehicule cible une action du pont`() {
2031
// bridgeAction=null est réservé aux actions locales (lancer une app, notifier).

0 commit comments

Comments
 (0)