Repository navigation
Expand file tree
/
Copy pathmise.toml
More file actions
306 lines (281 loc) · 12.4 KB
/
Copy pathmise.toml
File metadata and controls
306 lines (281 loc) · 12.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
[tools]
java = "17"
[env]
ANDROID_HOME = "{{env.HOME}}/Android/Sdk"
ANDROID_SDK_ROOT = "{{env.HOME}}/Android/Sdk"
_.path = [
"{{env.HOME}}/Android/Sdk/platform-tools",
"{{env.HOME}}/Android/Sdk/cmdline-tools/latest/bin",
]
# Google publishes no Automotive image for the vehicle's AAOS 9 / API 28. The two
# profiles therefore validate different axes and neither replaces an on-vehicle pass:
# emulator-car API 33 Automotive, with CarPropertyManager but the wrong OS version.
# emulator-screen API 28 tablet, with the target OS and panel geometry but no car service.
# The car's panel is 1920x720 at 160dpi and carries no system bars, so a layout gets all 720
# of them. An emulator does have bars, which take EMU_SYSTEM_UI off the panel before the
# activity sees it, so the panel is that much taller and the configuration then reports
# h720dp — the car's box. The old 1080 panel reported h908dp and hid every overflow.
EMU_CAR_AVD = "evchargepilot-car"
EMU_CAR_IMAGE = "system-images;android-33;android-automotive;x86_64"
EMU_SCREEN_AVD = "evchargepilot-screen"
EMU_SCREEN_IMAGE = "system-images;android-28;google_apis;x86_64"
EMU_WIDTH = "1920"
EMU_APP_HEIGHT = "720"
# Measured on the API 33 Automotive image: a 76dp status bar and a 96dp control bar.
EMU_SYSTEM_UI = "172"
EMU_HEIGHT = "892"
EMU_DENSITY = "160"
COMPILE_SDK = "36"
BUILD_TOOLS = "36.0.0"
[tasks.bootstrap]
description = "Install the required Android SDK platform and build tools"
run = '''
set -e
if [ -d "$ANDROID_HOME/platforms/android-$COMPILE_SDK" ]; then
echo "sdk.dir=$ANDROID_HOME" > local.properties
echo "Android SDK $COMPILE_SDK ready."
exit 0
fi
SDK="$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager"
if [ ! -x "$SDK" ]; then
echo "sdkmanager is missing from $ANDROID_HOME/cmdline-tools/latest." >&2
exit 1
fi
yes | "$SDK" --sdk_root="$ANDROID_HOME" --licenses > /dev/null
"$SDK" --sdk_root="$ANDROID_HOME" \
"platform-tools" "platforms;android-$COMPILE_SDK" "build-tools;$BUILD_TOOLS"
echo "sdk.dir=$ANDROID_HOME" > local.properties
'''
[tasks.build]
description = "Build the stable debug APK"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME assembleStableDebug'
[tasks.build-unstable]
description = "Build the unstable debug APK — the channel the validation drive runs on"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME assembleUnstableDebug'
[tasks.test]
description = "Run application and EVHardware JVM tests"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME testStableDebugUnitTest testUnstableDebugUnitTest :evhardware:testDebugUnitTest'
[tasks.lint]
description = "Run Android lint"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME lintStableDebug lintUnstableDebug'
[tasks.permissions]
description = "Permission-drift gate — the same one CI runs"
run = "bash .github/security/check-permissions.sh"
[tasks.check]
description = "What CI runs: permissions + lint + tests"
run = '''
set -e
bash .github/security/check-permissions.sh
./gradlew -Dorg.gradle.java.home=$JAVA_HOME \
:evhardware:testDebugUnitTest \
testStableDebugUnitTest testUnstableDebugUnitTest \
lintStableDebug lintUnstableDebug
'''
[tasks.release]
description = "Build the minified stable release APK"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME assembleStableRelease'
[tasks.clean]
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME clean'
[tasks.emulator-setup]
description = "Install emulator images and create the Automotive and API 28 AVDs"
run = '''
set -e
SDK="$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager"
AVDM="$ANDROID_HOME/cmdline-tools/latest/bin/avdmanager"
if [ ! -e /dev/kvm ]; then
echo "ERROR: /dev/kvm is unavailable; the emulator would be unusably slow." >&2
exit 1
fi
if ! id -nG | tr ' ' '\n' | grep -qx kvm; then
echo "WARNING: current user is not in the kvm group." >&2
fi
if [ ! -x "$SDK" ] || [ ! -x "$AVDM" ]; then
echo "Android command-line tools are missing; run 'mise run bootstrap' first." >&2
exit 1
fi
yes | "$SDK" --sdk_root="$ANDROID_HOME" --licenses > /dev/null
"$SDK" --sdk_root="$ANDROID_HOME" \
"emulator" "platform-tools" "$EMU_CAR_IMAGE" "$EMU_SCREEN_IMAGE"
create_avd() {
name="$1"; image="$2"; device="$3"
if "$AVDM" list avd 2>/dev/null | grep -q "Name: $name"; then
echo "AVD $name already exists"
else
echo no | "$AVDM" create avd -n "$name" -k "$image" -d "$device" --force
fi
cfg="$HOME/.android/avd/$name.avd/config.ini"
sed -i '/^hw.lcd/d;/^disk.dataPartition.size/d' "$cfg"
{
echo "hw.lcd.width=$EMU_WIDTH"
echo "hw.lcd.height=$EMU_HEIGHT"
echo "hw.lcd.density=$EMU_DENSITY"
echo "disk.dataPartition.size=4G"
} >> "$cfg"
echo "AVD $name configured at ${EMU_WIDTH}x${EMU_HEIGHT} @ ${EMU_DENSITY}dpi"
}
create_avd "$EMU_CAR_AVD" "$EMU_CAR_IMAGE" "automotive_1024p_landscape"
create_avd "$EMU_SCREEN_AVD" "$EMU_SCREEN_IMAGE" "pixel_c"
'''
# Software rendering is the reliable default under WSL2, where -gpu host commonly sees
# only Mesa llvmpipe and exits before the emulator window appears.
[tasks.emulator-car]
description = "Start the API 33 Automotive emulator"
run = '''
set -e
"$ANDROID_HOME/emulator/emulator" -avd "$EMU_CAR_AVD" \
-skin "${EMU_WIDTH}x${EMU_HEIGHT}" -gpu swiftshader_indirect \
-no-snapshot-load -no-snapshot-save -no-boot-anim &
ADB="$ANDROID_HOME/platform-tools/adb"
"$ADB" wait-for-device
for attempt in $(seq 1 120); do
[ "$("$ADB" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')" = "1" ] && break
[ "$attempt" -eq 120 ] && { echo "Automotive emulator boot timed out." >&2; exit 1; }
sleep 1
done
mise run emulator-viewport
# No GPS receiver in the emulator: the root `geo` task keeps a fixed Auzielle position fresh.
nohup mise run geo >/dev/null 2>&1 &
echo "Automotive emulator ready."
'''
[tasks.emulator-screen]
description = "Start the API 28 panel emulator"
run = '''
set -e
"$ANDROID_HOME/emulator/emulator" -avd "$EMU_SCREEN_AVD" \
-skin "${EMU_WIDTH}x${EMU_HEIGHT}" -gpu swiftshader_indirect \
-no-snapshot-load -no-snapshot-save -no-boot-anim &
ADB="$ANDROID_HOME/platform-tools/adb"
"$ADB" wait-for-device
for attempt in $(seq 1 120); do
[ "$("$ADB" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')" = "1" ] && break
[ "$attempt" -eq 120 ] && { echo "Screen emulator boot timed out." >&2; exit 1; }
sleep 1
done
mise run emulator-viewport
echo "Screen emulator ready."
'''
[tasks.emulator-viewport]
description = "Size the running emulator so the app window matches the car's 1920x720 viewport"
run = '''
set -e
ADB="$ANDROID_HOME/platform-tools/adb"
"$ADB" shell wm size "${EMU_WIDTH}x${EMU_HEIGHT}"
"$ADB" shell wm density "$EMU_DENSITY"
# The panel is the viewport plus the bars; if this emulator's bars are not EMU_SYSTEM_UI tall
# the app window is not the car's and every layout check made on it is measuring the wrong box.
# The configuration's own w/h, which is the box a layout is measured in — and display 0 only,
# because an Automotive image also publishes a cluster display and lists it first.
box=$("$ADB" shell dumpsys window displays \
| awk '/mDisplayId=0/{f=1} f && /overrideConfig/{match($0, /w[0-9]+dp h[0-9]+dp/); print substr($0, RSTART, RLENGTH); exit}')
want="w${EMU_WIDTH}dp h${EMU_APP_HEIGHT}dp"
if [ "$box" != "$want" ]; then
echo "Layouts would be measured in $box, not the car's $want: this emulator's system UI is not $EMU_SYSTEM_UI tall." >&2
exit 1
fi
echo "Layout box $box at ${EMU_DENSITY}dpi — the car's viewport."
'''
[tasks.emulator-stop]
description = "Stop the connected emulator"
run = '"$ANDROID_HOME/platform-tools/adb" emu kill || true'
[tasks.run]
description = "Build, install and launch on the connected emulator or vehicle"
depends = ["build"]
run = '''
set -e
ADB="$ANDROID_HOME/platform-tools/adb"
if [ -z "$($ADB devices | sed '1d' | grep -w device || true)" ]; then
echo "No device connected. Start emulator-car/emulator-screen or connect the vehicle." >&2
exit 1
fi
APK=$(ls -t app/build/outputs/apk/stable/debug/*.apk | head -1)
echo "Installing $APK"
"$ADB" install -r -g "$APK"
# A route needs a position and the emulator has no receiver. The task is a no-op when
# emulator-car already started one.
nohup mise run geo >/dev/null 2>&1 &
# seed-settings launches the app: the seed is read at start, so the install has to come first
# and the launch has to come after it. Without the local settings file it only launches.
SEED_PKG="com.evsuite.chargepilot" mise run seed-trips
SEED_PKG="com.evsuite.chargepilot" mise run seed-settings
'''
[tasks.run-unstable]
description = "Install and launch the unstable channel — probes, evidence capture, CP-055"
depends = ["build-unstable"]
run = '''
set -e
ADB="$ANDROID_HOME/platform-tools/adb"
if [ -z "$($ADB devices | sed '1d' | grep -w device || true)" ]; then
echo "No device connected. Start emulator-car/emulator-screen or connect the vehicle." >&2
exit 1
fi
APK=$(ls -t app/build/outputs/apk/unstable/debug/*.apk | head -1)
echo "Installing $APK"
"$ADB" install -r -g "$APK"
nohup mise run geo >/dev/null 2>&1 &
SEED_PKG="com.evsuite.chargepilot.unstable" mise run seed-trips
SEED_PKG="com.evsuite.chargepilot.unstable" mise run seed-settings
'''
# Every screen in this app reads recorded history: the trip ledger, the plot, the arrival
# forecast, the speed comparison, the health estimate. A fresh emulator has none, so every one of
# them renders its empty state and the rendering cannot be reviewed. This drops a recorded drive,
# a short errand and eight measurable discharges — checked in, no keys, no personal position —
# into the app's own files, so run/run-unstable always start with data. TRIP_FILE= and
# LEDGER_FILE= seed a different history.
[tasks.seed-trips]
description = "Inject the reference trips and battery ledger so the screens render with data"
run = '''
set -e
ADB="$ANDROID_HOME/platform-tools/adb"
TRIPS="${TRIP_FILE:-evchargepilot-trips.json}"
LEDGER="${LEDGER_FILE:-evchargepilot-battery-ledger.json}"
PKG="${SEED_PKG:-com.evsuite.chargepilot}"
if [ -z "$($ADB devices | sed '1d' | grep -w device || true)" ]; then
echo "No device connected. Start emulator-car/emulator-screen first." >&2
exit 1
fi
USER_ID="$($ADB shell am get-current-user | tr -d '\r\n')"
# Same shape as seed-settings: only run-as can write into the app's data directory, and the
# redirect has to happen inside it.
"$ADB" shell "run-as $PKG --user $USER_ID mkdir -p /data/user/$USER_ID/$PKG/files"
seed() {
"$ADB" push "$1" /data/local/tmp/seed-history.json >/dev/null
"$ADB" shell "run-as $PKG --user $USER_ID sh -c 'cat /data/local/tmp/seed-history.json > /data/user/$USER_ID/$PKG/files/$2'"
"$ADB" shell rm /data/local/tmp/seed-history.json
}
seed "$TRIPS" trips.json
seed "$LEDGER" battery-ledger.json
echo "Trips and battery ledger seeded into $PKG (user $USER_ID)."
'''
[tasks.logs]
description = "Follow EVChargePilot and shared hardware logs"
run = 'adb logcat -s EVChargePilot:V EV_HW:V AndroidRuntime:E'
# The emulator has no USB stick and no driver to type a key on a touch keyboard. This drops the
# real settings into a debug build's own files directory, where ChargePilotApp applies them once
# at the next start. Debug builds only — a release build has no such path. The file it reads is
# gitignored: it carries API keys in clear text, exactly like the stick does.
[tasks.seed-settings]
description = "Load evchargepilot-settings.local.json into the connected emulator (debug builds)"
run = '''
set -e
ADB="$ANDROID_HOME/platform-tools/adb"
FILE="${SEED_FILE:-evchargepilot-settings.local.json}"
PKG="${SEED_PKG:-com.evsuite.chargepilot}"
if [ -z "$($ADB devices | sed '1d' | grep -w device || true)" ]; then
echo "No device connected. Start emulator-car/emulator-screen first." >&2
exit 1
fi
USER_ID="$($ADB shell am get-current-user | tr -d '\r\n')"
if [ -f "$FILE" ]; then
"$ADB" push "$FILE" /data/local/tmp/seed-settings.json
# The redirect has to run inside run-as, not in the shell that invokes it: the outer shell is
# uid shell, which cannot write into an app's data directory, and its cwd is /.
"$ADB" shell "run-as $PKG --user $USER_ID mkdir -p /data/user/$USER_ID/$PKG/files"
"$ADB" shell "run-as $PKG --user $USER_ID sh -c 'cat /data/local/tmp/seed-settings.json > /data/user/$USER_ID/$PKG/files/seed-settings.json'"
"$ADB" shell rm /data/local/tmp/seed-settings.json
echo "Settings seeded into $PKG (user $USER_ID)."
else
echo "No $FILE — launching without seeding. Copy evchargepilot-settings.json to it and put the real keys in."
fi
"$ADB" shell am force-stop "$PKG"
"$ADB" shell am start --user "$USER_ID" -n "$PKG/com.evsuite.chargepilot.MainActivity"
'''