@@ -52,16 +52,13 @@ jobs:
5252 - name : Build debug APK
5353 run : ./gradlew assembleDebug
5454
55- - name : Build androidTest APK
56- run : ./gradlew assembleDebugAndroidTest
57-
5855 - name : Enable KVM
5956 run : |
6057 echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
6158 sudo udevadm control --reload-rules
6259 sudo udevadm trigger --name-match=kvm
6360
64- - name : Start Android emulator
61+ - name : Start Android emulator and run test
6562 uses : reactivecircus/android-emulator-runner@v2
6663 with :
6764 api-level : 30
@@ -71,69 +68,223 @@ jobs:
7168 emulator-options : -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim
7269 disable-animations : true
7370 script : |
71+ set -e
72+
7473 echo "=== Emulator booted ==="
7574 adb shell getprop ro.build.version.sdk
7675 adb shell getprop ro.product.cpu.abi
7776
78- echo "=== Installing APKs ==="
77+ echo "=== Installing APK ==="
7978 adb install -r app/build/outputs/apk/debug/app-debug.apk
80- adb install -r app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk
8179
8280 echo "=== Granting permissions ==="
8381 adb shell pm grant com.scisammy.ubuntuandroid android.permission.READ_EXTERNAL_STORAGE || true
8482 adb shell pm grant com.scisammy.ubuntuandroid android.permission.WRITE_EXTERNAL_STORAGE || true
8583
84+ echo "=== Pre-check: native libs ==="
85+ adb shell "find /data/app/ -name 'lib_proot*' 2>/dev/null" || echo "no proot lib found"
86+ adb shell "find /data/app/ -name 'lib_busybox*' 2>/dev/null" || echo "no busybox lib found"
87+
8688 echo "=== Clearing logcat ==="
8789 adb logcat -c
8890
89- echo "=== Running instrumentation tests ==="
90- adb shell am instrument -w -e class tech.ula.ui.UbuntuLaunchTest com.scisammy.ubuntuandroid.test/androidx.test.runner.AndroidJUnitRunner 2>&1 || true
91+ echo "=== Launching app ==="
92+ adb shell am start -n com.scisammy.ubuntuandroid/.MainActivity
93+ sleep 5
9194
92- echo "=== Capturing logcat ==="
93- adb logcat -d -s "tech.ula:*" "busybox:*" "ULA:*" "System.out:*" "System.err:*" > /tmp/logcat.txt 2>&1 || true
95+ echo "=== UI dump after launch ==="
96+ adb shell uiautomator dump /sdcard/ui_launch.xml 2>/dev/null || true
97+ adb pull /sdcard/ui_launch.xml /tmp/ui_launch.xml 2>/dev/null || true
98+ cat /tmp/ui_launch.xml 2>/dev/null || echo "no ui dump"
9499
95- echo "=== Checking if server is running ==="
96- adb shell "netstat -tlnp 2>/dev/null | grep 2022" || echo "Port 2022 not listening"
97- adb shell "ps -ef 2>/dev/null | grep dropbear" || echo "No dropbear process"
98- adb shell "ps -ef 2>/dev/null | grep proot" || echo "No proot process"
100+ echo "=== Check logcat for errors ==="
101+ adb logcat -d | grep -i "error\|exception\|crash\|fatal\|missing" | tail -30 || echo "no errors found"
99102
100- echo "=== Listing support dir ==="
101- adb shell "ls -la /data/data/com.scisammy.ubuntuandroid/files/support/ 2>/dev/null" || echo "Support dir not found"
102- adb shell "ls -la /data/data/com.scisammy.ubuntuandroid/files/ 2>/dev/null" || echo "Files dir not found"
103+ echo "=== Wait for app list to load (20s) ==="
104+ sleep 20
103105
104- echo "=== Dumping UI hierarchy ==="
105- adb shell uiautomator dump /sdcard/ui_dump.xml 2>/dev/null || true
106- adb pull /sdcard/ui_dump.xml /tmp/ui_dump.xml 2>/dev/null || true
106+ echo "=== UI dump after wait ==="
107+ adb shell uiautomator dump /sdcard/ui_loaded.xml 2>/dev/null || true
108+ adb pull /sdcard/ui_loaded.xml /tmp/ui_loaded.xml 2>/dev/null || true
109+ cat /tmp/ui_loaded.xml 2>/dev/null || echo "no ui dump"
107110
108- echo "=== Taking screenshot ==="
109- adb shell screencap -p /sdcard/screenshot.png 2>/dev/null || true
110- adb pull /sdcard/screenshot.png /tmp/screenshot.png 2>/dev/null || true
111+ echo "=== Look for Ubuntu in the list ==="
112+ adb shell uiautomator dump /sdcard/ui_full.xml 2>/dev/null || true
113+ adb pull /sdcard/ui_full.xml /tmp/ui_full.xml 2>/dev/null || true
114+ grep -i "ubuntu" /tmp/ui_full.xml 2>/dev/null || echo "Ubuntu not found in UI"
111115
112- echo "=== Checking filesystem dirs ==="
113- adb shell "ls /data/data/com.scisammy.ubuntuandroid/files/ 2>/dev/null" || echo "No files dir"
116+ echo "=== Try clicking Ubuntu (first app item) ==="
117+ # Get bounds of first list item and click center
118+ BOUNDS=$(adb shell uiautomator dump /dev/tty 2>/dev/null | grep -oP 'resource-id="com.scisammy.ubuntuandroid:id/apps_name"[^>]*bounds="\[\d+,\d+\]\[\d+,\d+\]"' | head -1 | grep -oP 'bounds="\[\d+,\d+\]\[\d+,\d+\]"')
119+ echo "Ubuntu bounds: $BOUNDS"
120+ if [ -n "$BOUNDS" ]; then
121+ # Parse bounds
122+ X1=$(echo "$BOUNDS" | grep -oP '\[(\d+),' | head -1 | tr -dc '0-9')
123+ Y1=$(echo "$BOUNDS" | grep -oP ',(\d+)\]' | head -1 | tr -dc '0-9')
124+ X2=$(echo "$BOUNDS" | grep -oP '\[(\d+),' | tail -1 | tr -dc '0-9')
125+ Y2=$(echo "$BOUNDS" | grep -oP ',(\d+)\]' | tail -1 | tr -dc '0-9')
126+ CX=$(( (X1 + X2) / 2 ))
127+ CY=$(( (Y1 + Y2) / 2 ))
128+ echo "Clicking at ($CX, $CY)"
129+ adb shell input tap $CX $CY
130+ else
131+ echo "Could not find Ubuntu, trying tap at common position"
132+ adb shell input tap 540 400
133+ fi
134+ sleep 3
114135
115- echo "=== DONE ==="
136+ echo "=== UI dump after clicking Ubuntu ==="
137+ adb shell uiautomator dump /sdcard/ui_after_click.xml 2>/dev/null || true
138+ adb pull /sdcard/ui_after_click.xml /tmp/ui_after_click.xml 2>/dev/null || true
139+ cat /tmp/ui_after_click.xml 2>/dev/null || echo "no ui dump"
116140
117- - name : Upload logcat
118- if : always()
119- uses : actions/upload-artifact@v4
120- with :
121- name : logcat
122- path : /tmp/logcat.txt
123- if-no-files-found : ignore
141+ echo "=== Check for credentials dialog ==="
142+ adb shell "dumpsys activity top | grep -i 'ACTIVITY\|DIALOG\|EditText\|username\|password'" || true
143+
144+ echo "=== Type username ==="
145+ adb shell input tap 540 300
146+ sleep 1
147+ adb shell input text "user"
148+ adb shell input keyevent 61 # TAB
149+ sleep 1
150+ adb shell input text "pass"
151+ adb shell input keyevent 61 # TAB
152+ adb shell input text "vncpass"
153+ sleep 1
154+
155+ echo "=== Click OK button (positive button in dialog) ==="
156+ # Dialog positive button is typically at bottom-right
157+ adb shell uiautomator dump /sdcard/ui_dialog.xml 2>/dev/null || true
158+ adb pull /sdcard/ui_dialog.xml /tmp/ui_dialog.xml 2>/dev/null || true
159+ # Find the OK button
160+ OK_BOUNDS=$(cat /tmp/ui_dialog.xml 2>/dev/null | grep -oP 'text="OK"[^>]*bounds="\[\d+,\d+\]\[\d+,\d+\]"' | grep -oP 'bounds="\[\d+,\d+\]\[\d+,\d+\]"')
161+ if [ -n "$OK_BOUNDS" ]; then
162+ X1=$(echo "$OK_BOUNDS" | grep -oP '\[(\d+),' | head -1 | tr -dc '0-9')
163+ Y1=$(echo "$OK_BOUNDS" | grep -oP ',(\d+)\]' | head -1 | tr -dc '0-9')
164+ X2=$(echo "$OK_BOUNDS" | grep -oP '\[(\d+),' | tail -1 | tr -dc '0-9')
165+ Y2=$(echo "$OK_BOUNDS" | grep -oP ',(\d+)\]' | tail -1 | tr -dc '0-9')
166+ CX=$(( (X1 + X2) / 2 ))
167+ CY=$(( (Y1 + Y2) / 2 ))
168+ echo "Clicking OK at ($CX, $CY)"
169+ adb shell input tap $CX $CY
170+ else
171+ echo "OK button not found, pressing enter"
172+ adb shell input keyevent 66 # ENTER
173+ fi
174+ sleep 3
175+
176+ echo "=== UI dump after credentials ==="
177+ adb shell uiautomator dump /sdcard/ui_after_creds.xml 2>/dev/null || true
178+ adb pull /sdcard/ui_after_creds.xml /tmp/ui_after_creds.xml 2>/dev/null || true
179+ cat /tmp/ui_after_creds.xml 2>/dev/null || echo "no ui dump"
180+
181+ echo "=== Check for SSH radio button ==="
182+ adb shell uiautomator dump /sdcard/ui_conn.xml 2>/dev/null || true
183+ adb pull /sdcard/ui_conn.xml /tmp/ui_conn.xml 2>/dev/null || true
184+ SSH_BOUNDS=$(cat /tmp/ui_conn.xml 2>/dev/null | grep -oP 'text="SSH"[^>]*bounds="\[\d+,\d+\]\[\d+,\d+\]"' | grep -oP 'bounds="\[\d+,\d+\]\[\d+,\d+\]"')
185+ if [ -n "$SSH_BOUNDS" ]; then
186+ X1=$(echo "$SSH_BOUNDS" | grep -oP '\[(\d+),' | head -1 | tr -dc '0-9')
187+ Y1=$(echo "$SSH_BOUNDS" | grep -oP ',(\d+)\]' | head -1 | tr -dc '0-9')
188+ X2=$(echo "$SSH_BOUNDS" | grep -oP '\[(\d+),' | tail -1 | tr -dc '0-9')
189+ Y2=$(echo "$SSH_BOUNDS" | grep -oP ',(\d+)\]' | tail -1 | tr -dc '0-9')
190+ CX=$(( (X1 + X2) / 2 ))
191+ CY=$(( (Y1 + Y2) / 2 ))
192+ echo "Clicking SSH at ($CX, $CY)"
193+ adb shell input tap $CX $CY
194+ fi
195+ sleep 1
196+
197+ echo "=== Click OK for connection type ==="
198+ adb shell uiautomator dump /sdcard/ui_conn2.xml 2>/dev/null || true
199+ adb pull /sdcard/ui_conn2.xml /tmp/ui_conn2.xml 2>/dev/null || true
200+ OK_BOUNDS2=$(cat /tmp/ui_conn2.xml 2>/dev/null | grep -oP 'text="OK"[^>]*bounds="\[\d+,\d+\]\[\d+,\d+\]"' | grep -oP 'bounds="\[\d+,\d+\]\[\d+,\d+\]"')
201+ if [ -n "$OK_BOUNDS2" ]; then
202+ X1=$(echo "$OK_BOUNDS2" | grep -oP '\[(\d+),' | head -1 | tr -dc '0-9')
203+ Y1=$(echo "$OK_BOUNDS2" | grep -oP ',(\d+)\]' | head -1 | tr -dc '0-9')
204+ X2=$(echo "$OK_BOUNDS2" | grep -oP '\[(\d+),' | tail -1 | tr -dc '0-9')
205+ Y2=$(echo "$OK_BOUNDS2" | grep -oP ',(\d+)\]' | tail -1 | tr -dc '0-9')
206+ CX=$(( (X1 + X2) / 2 ))
207+ CY=$(( (Y1 + Y2) / 2 ))
208+ echo "Clicking OK at ($CX, $CY)"
209+ adb shell input tap $CX $CY
210+ else
211+ adb shell input keyevent 66
212+ fi
213+
214+ echo "=== Waiting for server to start (120s) ==="
215+ sleep 10
216+
217+ echo "=== Progress check (10s) ==="
218+ adb shell uiautomator dump /sdcard/ui_progress1.xml 2>/dev/null || true
219+ adb pull /sdcard/ui_progress1.xml /tmp/ui_progress1.xml 2>/dev/null || true
220+ cat /tmp/ui_progress1.xml 2>/dev/null | grep -oP 'text="[^"]*"' | head -20 || true
221+
222+ sleep 20
223+
224+ echo "=== Progress check (30s) ==="
225+ adb shell uiautomator dump /sdcard/ui_progress2.xml 2>/dev/null || true
226+ adb pull /sdcard/ui_progress2.xml /tmp/ui_progress2.xml 2>/dev/null || true
227+ cat /tmp/ui_progress2.xml 2>/dev/null | grep -oP 'text="[^"]*"' | head -20 || true
228+
229+ sleep 30
230+
231+ echo "=== Progress check (60s) ==="
232+ adb shell uiautomator dump /sdcard/ui_progress3.xml 2>/dev/null || true
233+ adb pull /sdcard/ui_progress3.xml /tmp/ui_progress3.xml 2>/dev/null || true
234+ cat /tmp/ui_progress3.xml 2>/dev/null | grep -oP 'text="[^"]*"' | head -20 || true
235+
236+ sleep 30
237+
238+ echo "=== Progress check (90s) ==="
239+ adb shell uiautomator dump /sdcard/ui_progress4.xml 2>/dev/null || true
240+ adb pull /sdcard/ui_progress4.xml /tmp/ui_progress4.xml 2>/dev/null || true
241+ cat /tmp/ui_progress4.xml 2>/dev/null | grep -oP 'text="[^"]*"' | head -20 || true
242+
243+ sleep 30
244+
245+ echo "=== Final diagnostics (120s+) ==="
246+ adb shell uiautomator dump /sdcard/ui_final.xml 2>/dev/null || true
247+ adb pull /sdcard/ui_final.xml /tmp/ui_final.xml 2>/dev/null || true
248+
249+ echo "=== Final UI state ==="
250+ cat /tmp/ui_final.xml 2>/dev/null | grep -oP 'text="[^"]*"' | head -30 || true
251+
252+ echo "=== Support directory ==="
253+ adb shell "ls -la /data/data/com.scisammy.ubuntuandroid/files/support/ 2>/dev/null" || echo "support dir not found"
254+
255+ echo "=== Files directory ==="
256+ adb shell "ls -la /data/data/com.scisammy.ubuntuandroid/files/ 2>/dev/null" || echo "files dir not found"
257+
258+ echo "=== Check port 2022 ==="
259+ adb shell "netstat -tlnp 2>/dev/null | grep 2022" || echo "port 2022 not listening"
260+
261+ echo "=== Check proot/dropbear processes ==="
262+ adb shell "ps -ef 2>/dev/null | grep -E 'proot|dropbear|busybox'" || echo "no relevant processes"
263+
264+ echo "=== Logcat errors ==="
265+ adb logcat -d | grep -iE "error|exception|fail|missing|crash" | grep -v "chromium\|DEBUG\|sentry" | tail -50 || echo "no errors"
266+
267+ echo "=== Logcat ula tags ==="
268+ adb logcat -d -s "Ula:*" "ULA:*" "tech.ula:*" "LocalServerManager:*" "BusyboxExecutor:*" | tail -50 || true
269+
270+ echo "=== Screenshot ==="
271+ adb shell screencap -p /sdcard/screenshot_final.png 2>/dev/null || true
272+ adb pull /sdcard/screenshot_final.png /tmp/screenshot_final.png 2>/dev/null || true
273+
274+ echo "=== DONE ==="
124275
125- - name : Upload UI dump
276+ - name : Upload UI dumps
126277 if : always()
127278 uses : actions/upload-artifact@v4
128279 with :
129- name : ui-dump
130- path : /tmp/ui_dump .xml
280+ name : ui-dumps
281+ path : /tmp/ui_* .xml
131282 if-no-files-found : ignore
132283
133284 - name : Upload screenshot
134285 if : always()
135286 uses : actions/upload-artifact@v4
136287 with :
137288 name : screenshot
138- path : /tmp/screenshot .png
289+ path : /tmp/screenshot_final .png
139290 if-no-files-found : ignore
0 commit comments