-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathethernally.sh
executable file
·627 lines (450 loc) · 22.5 KB
/
ethernally.sh
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
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
#!/bin/sh
# this script automatically sets permanent adb via wifi and eventually start scrcpy through WiFi
# set the default adbd listening port. You can change it accordingly..
port="5555"
######################################################################################################################
# clear
# check adb presence on host
if ! type adb >/dev/null; then
echo "Please install adb and/or add it to system PATH if downloaded as standalone binary"
exit 1
fi
# perl adaptation of readlink -f for compatibility with MacOS
readlinkf() {
perl -MCwd -le 'print Cwd::abs_path shift' "$1"
}
DIRECTORY=$(cd "$(dirname "$(readlinkf "$0")")" && pwd)
echo "Running script from $DIRECTORY"
last_working_device="$DIRECTORY/last_working_device.conf"
touch "${last_working_device}"
debug_log="$DIRECTORY/debug.log"
true >"${debug_log}"
# empty log
######################################################################################################################
# FUNCTIONS (order matters!)
get_device_serial() {
adb_devices=$(adb devices -l)
# echo "adb_devices: ${adb_devices}"
usb_device_serial=$(echo "${adb_devices}" | grep -w device | grep -v '\.' | awk '{print $1}')
# get USB connected device serial
echo "${usb_device_serial}"
}
check_usb_connection() {
echo "DEBUG> killing adb server.."
adb kill-server
while [ -z "${usb_device_serial}" ]; do
adb usb 2>/dev/null
sleep 2
# wait to be ready
usb_device_serial=$(get_device_serial)
# echo "usb_device_serial: ${usb_device_serial}"
usb_device=$(adb devices -l | grep -w device | grep -v '\.' | awk -F: '{print $4}' | awk '{print $1}')
# get device name
# echo "usb_device: ${usb_device}"
if [ -n "${usb_device_serial}" ]; then
echo ""
echo "device(s) connected via USB cable: ${usb_device}"
# print USB conneted device serial
break
fi
printf "."
done
echo "usb_device_serial: ${usb_device_serial}"
}
check_root() {
echo "Checking root.."
elevated_UID=$(adb -s "${device}" shell su --command "id -u" | sed 's/\r$//g')
# trying to get attached device wlan0 ip
# sed is required to fix line ending by removing dos carriage return (cygwin)
# echo "elevated_UID: ${elevated_UID}"
if [ -z "${elevated_UID}" ]; then
echo "Your device needs to be rooted for allowing permanent WiFi connectivity through ADB"
rooted=0
# echo "rooted: ${rooted}"
# exit 1
else
echo "Device is rooted. Moving on.."
rooted=1
echo ""
fi
echo "rooted=${rooted}" >>"${debug_log}"
}
start_wifi_connection() {
usb_device_serial=$(get_device_serial)
adb -s "${usb_device_serial}" shell "svc wifi enable"
while [ -z "${wlan0_IP}" ]; do
wlan0_IP=$(adb -s "${usb_device_serial}" shell ip -f inet addr show wlan0 2>/dev/null |
grep inet |
awk '{print $2}' |
awk -F / '{print $1}')
if [ -n "${wlan0_IP}" ]; then
echo "${wlan0_IP}"
break
fi
done
}
set_last_working_device_info() {
echo "${socket}" >"${last_working_device}"
manufacturer=$(adb -s "${socket}" shell "getprop ro.product.manufacturer")
# Manufacturer
echo "Manufacturer: ${manufacturer}" >>"${last_working_device}"
android_version=$(adb -s "${socket}" shell "getprop ro.build.version.release")
# device android version
echo "Android Version: ${android_version}" >>"${last_working_device}"
sdk_version=$(adb -s "${socket}" shell "getprop ro.build.version.sdk")
# sdk version
echo "SDK Version: ${sdk_version}" >>"${last_working_device}"
product_name=$(adb -s "${socket}" shell "getprop ro.product.name")
# product name
echo "Product Name: ${product_name}" >>"${last_working_device}"
model=$(adb -s "${socket}" shell "getprop ro.product.model")
# device model
echo "Model: ${model}" >>"${last_working_device}"
}
usb_connection() {
# ((device does not have WiFi turned on) OR (does not have an IP set)) OR (device is NOT already attached via (tcp/wifi OR USB))
echo ""
echo ""
echo "!!! READ CAREFULLY !!!"
echo "1. Please plug USB cable and enable USB debugging (To unlock the hidden Developer tools/options menu, go to Android Settings > About > Press on 'build number' 7 times. Then go to android settings > developer tools/options and enable 'USB debugging')"
echo ""
echo "2. You should also check 'Disable adb authorization timeout' so that the adb authorization for systems that have not reconnected within the default (7days) is not revoked, thus to be able to reconnect in the future without interaction."
echo ""
echo "3. If asked, allow USB debugging on your Android device by allowing your computer's RSA key fingerprint. Also check the 'Always allow from this computer' checkbox to allow future connections"
echo ""
echo ""
echo ""
echo "Checking if USB cable is connected and USB debugging enabled and authorized.."
echo "......"
check_usb_connection
echo ""
device=${usb_device_serial}
# check if device is rooted
check_root "${device}"
# if device is not rooted
if [ ${rooted} -eq 0 ]; then
echo "Device is not rooted. Moving on.."
adb tcpip ${port}
sleep 5
# give adb some time to restart. do now lower this timeout!
else
# device rooted
#Set props
adb -s "${usb_device_serial}" shell su --command "setprop service.adb.tcp.port ${port}" &&
printf "Property service.adb.tcp.port was set to: " &&
adb -s "${usb_device_serial}" shell su --command "getprop service.adb.tcp.port"
# set adbd session tcp port
adb -s "${usb_device_serial}" shell su --command "setprop persist.adb.tcp.port ${port}" &&
printf "Property persist.adb.tcp.port was set to: " &&
adb -s "${usb_device_serial}" shell su --command "getprop persist.adb.tcp.port"
# set adbd persistent(boot) tcp port
echo "Restarting adbd"
adb -s "${usb_device_serial}" shell "su --command 'stop adbd ; sleep 2 ; start adbd'"
# restart adbd daemon to start listening on port (tcp/wifi); sleep is required to allow smooth service stop
echo "Restarted adbd"
sleep 5
# give adbd some time to restart. If sleeping less than 5 seconds, it might throw error: adb(.exe): no devices/emulators found
fi
echo "Attempting to start Wi-Fi on the device.."
wlan0_IP=$(start_wifi_connection)
#echo "wlan0_IP: ${wlan0_IP}"
socket="${wlan0_IP}:${port}"
echo "new socket: ${socket}"
status=$(adb connect "${socket}")
echo "ADB connect status: ${status}" >>"${debug_log}"
# adb returns exit code 0 even if cannot connect. not reliable...
if [ "${status#*cannot}" != "${status}" ]; then
# posix trick to determine if status contains word "cannot"
# EXAMPLE "cannot" ERRORS:
# 1. "cannot connect to <wlan0_IP>:5555: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (10060)"
# 2. "cannot resolve host 'null' and port 5555: No such host is known. (11001)"
# 3. "cannot connect to <IP>:5555: No connection could be made because the target machine actively refused it. (10061)"
echo "Could not connect via adb to WiFi device"
connected="0"
echo "connected: false"
else
# Wi-Fi connectivity worked
echo "Connecting via wifi.."
adb connect "${socket}"
# reconnect to shell via wifi. You can unplug USB cable at this stage. scrcpy should work now
# 0 if failed ; 1 if connected
connected="1"
echo "connected: true"
# echo "connected: ${connected}"
# set last known working device
set_last_working_device_info
echo "Device ready!"
echo ""
fi
echo "connected=${connected}" >>"${debug_log}"
}
success_message() {
echo "######################################"
echo "You may unplug the USB cable if previously inserted."
# echo "Optionally you can mirror your screen with scrcpy."
echo "######################################"
echo "Enjoy a smooth wireless experience!"
echo "######################################"
echo ""
}
print_connections() {
# adb devices -l
# print attached devices (both USB and wifi/tcp are connected now)
socket=$(adb devices -l | grep -w device | grep ${port} | awk '{print $1}')
# echo "socket: ${socket}"
# echo "ADB TCP Connections:"
while [ -z "${connections}" ]; do
connections=$(adb -s "${socket}" shell "netstat -tupna | grep ${port}" 2>/dev/null)
# optionally, show that adbd daemon is listening, and the established connection
exitCode=$?
if [ "${exitCode}" -eq 0 ]; then
connectionState=1
else
connectionState=0
fi
if [ ${connectionState} ] && [ -n "${connections}" ]; then
# echo "${connections}" #print wlan0 ip
break
fi
sleep 1
done
}
mirror() {
echo "Attempting screen mirroring.."
# REF: https://github.com/Genymobile/scrcpy/blob/master/doc/device.md
# See also shortcuts: https://github.com/Genymobile/scrcpy/blob/master/doc/shortcuts.md
# stayAwake="--stay-awake" # stay-awake disabled. https://github.com/fusionneur/ethernally/issues/21. If the device is not plugged in (i.e. only connected over TCP/IP), --stay-awake has no effect (this is the Android behavior).
# WARNING: developer options -> disable permission monitoring --- could help with this but reduces device security. Don't enable it !
# turnScreenOff="--turn-screen-off" # on Android 12, app lock screen and fingerprint security popup show black screen on scrcpy => keep screen on so that you can easilly unlock/authorize
maxSize="--max-size"
# Max resollution Full HD (1920), 2K (2160), 4K (4096)..
maxSizeValue="1920"
# renderDriver="--render-driver=direct3d" #direct3d, opengl (slower, prone to crash with segmentation fault on Windows) ; comment to automatically detect best driver
maxFps="--max-fps"
maxFpsValue="60" # scrcpy matches with video FPS running on device (eg. even if you have 90 FPS set, if the video runs at 24 FPS this will take precedence). You can monitor FPS with ALT+I
videoBitRate="--video-bit-rate"
videoBitRateValue="20M" # or lower (4MB) for compatibility. scrcpy automatically lowers FPS and bitrate if needed
audioBitRate="--audio-bit-rate"
audioBitRateValue="320K"
# on Android 12+, audio works out of the box
# REF: https://github.com/Genymobile/scrcpy/blob/master/doc/audio.md
options=$(printf %s "${socket} ${maxSize} ${maxSizeValue} ${maxFps} ${maxFpsValue} ${videoBitRate} ${videoBitRateValue} ${audioBitRate} ${audioBitRateValue}")
echo "Parameters: ${options}"
scrcpyCommand="scrcpy -s ${options} &"
# scrcpyCommand="scrcpy --tcpip=${options} &"
# scrcpyCommand="scrcpy &"
# Eg. # scrcpy -s <IP> --stay-awake --turn-screen-off --max-size 1920 --max-fps 45 --bit-rate 6M
# scrcpy -s "${socket}" "${options[@]}" &
# removed flags: ${stayAwake} ${turnScreenOff}
eval "${scrcpyCommand}"
# "${options}" &
# >/dev/null
# mirror android screen via wifi, assuming that scrcpy is already installed or added to PATH ; modify custom options as desired
# scrcpy-noconsole -s "${socket}" --stay-awake --turn-screen-off -m 2160 --render-driver=opengl --max-fps 60 --bit-rate 6M & > /dev/null #mirror android screen via wifi, assuming that scrcpy is already installed or added to PATH ; modify custom options as desired ; this is for cygwin
}
ethernally() {
set_last_working_device_info
# echo "socket: ${socket}"
print_connections
mirror
success_message
sleep 3
# wait for scrcpy to start mirroring
adb -s "${socket}" shell
# uncomment to get you straight into android shell (you can comment this line)
# from here you can 'su -' to drop to root shell
# exit 0
}
try_last_known_device() {
echo ""
echo "Trying last known working device. Please have patience... (max 1 minute)"
if [ -s "${last_working_device}" ]; then
last_working_IP=$(grep -E -o "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){1,3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" "${last_working_device}")
# echo "Last known working IP: ${last_working_IP}"
last_Working_port=$(grep "${last_working_IP}" "${last_working_device}" | awk -F [:] '{print $2}')
# echo "Last known working port: ${last_Working_port}"
last_working_socket="${last_working_IP}:${last_Working_port}"
# if [ "${last_working_socket}" != "${socket}" ]; then
socket="${last_working_socket}"
echo "Last known working socket: ${socket}"
status=$(adb connect "${socket}")
echo "status: ${status}"
# adb returns exit code 0 even if it cannot connect. not reliable... Need extra error handling:
if [ "${status#*failed}" != "${status}" ]; then
# posix trick to determine if status contains word "failed"
# 1. "failed to authenticate to <IP>:<PORT>"
# 2. "cannot connect to <IP>:<PORT>: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (10060)" [!!! this error contains both 'failed' and 'cannot' keywords, but 'failed' keyword is checked first]
echo "Failed to authenticate via ADB to the automatically detected WiFi device or Failed because connected host has failed to respond"
echo "You must authorize device via USB cable..."
connected="0"
echo "connected: false"
usb_connection
else
if [ "${status#*cannot}" != "${status}" ]; then
# posix trick to determine if status contains word "cannot"
# EXAMPLE "cannot" ERRORS:
# 1. cannot connect to <wlan0_IP>:5555: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (10060)
# 2. cannot resolve host 'null' and port 5555: No such host is known. (11001)
# 3. cannot connect to <IP>:5555: No connection could be made because the target machine actively refused it. (10061)
echo "Could not connect via ADB to last known WiFi device"
echo ""
connected="0"
echo "connected: false"
printf "" >"${last_working_device}"
# remove last known working device
else
echo "Connected via ADB to last known WiFi device:"
cat "${last_working_device}"
echo ""
connected="1"
echo "connected: true"
fi
fi
# else
#echo "Skipping verifying connection"
#echo "Last known working device is the same as the one reported by ADB attached devices"
# fi# this check might not be needed anymore..
else
echo "There is no last known working device."
fi
}
#######################################################################################################
# MAIN
# CASES
# usb wifi#
# 0 0
# 1 0
# 0 1
# 1 1
# try wifi connection first
echo "Attempting to discover any attached devices.."
adb devices -l
echo ""
socket=$(adb devices -l | grep ${port} | awk '{print $1}')
# try to get attached device wlan0 ip, even if offline
echo "Disconnecting adb devices.."
adb disconnect >/dev/null
# upon reboot, sometimes even if connected, shell will give "error: closed" on first attempt, but on second will work. Need to disconnect and reconnect to make sure the connection is ok. At this point any previous attatched devices will no longer be attatched.
echo "DEBUG> killing adb server.."
adb kill-server
if [ -z "${socket}" ]; then
echo "There are no WiFi devices automatically detected/attached - as reported by ADB."
socket="null"
# set to null so that adb connect fails
connected="0"
echo "connected: false"
try_last_known_device
echo "last known device connected=${connected}" >"${debug_log}"
else
echo "socket not null. Devices were attatched."
echo "Attempting ADB connection via Wi-Fi to the attatched device. Please wait..."
status=$(adb connect "${socket}")
# adb returns exit code 0 even if it cannot connect. not reliable... Need extra error handling:
if [ "${status#*failed}" != "${status}" ]; then
# posix trick to determine if status contains word "failed"
# 1. "failed to authenticate to <IP>:<PORT>"
# 2. "cannot connect to <IP>:<PORT>: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (10060)" [!!! this error contains both 'failed' and 'cannot' keywords, but 'failed' keyword is checked first]
echo "Failed to authenticate via ADB to the automatically detected WiFi device"
try_last_known_device
echo "Disconnecting adb devices.."
# workaround - bug/feature? able to connect to unauthorized device
adb disconnect >/dev/null
echo "DEBUG> killing adb server.."
adb kill-server
echo "Re-attempting ADB connection via Wi-Fi to the attatched device. Please wait..."
status=$(adb connect "${socket}")
if [ "${status#*cannot}" = "${status}" ] && [ "${status#*failed}" = "${status}" ]; then
# posix trick to determine if status contains words "failed" or "cannot"
# EXAMPLE "cannot" ERRORS:
# 1. "cannot connect to <wlan0_IP>:5555: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (10060)"
# 2. "cannot resolve host 'null' and port 5555: No such host is known. (11001)"
# 3. "cannot connect to <IP>:5555: No connection could be made because the target machine actively refused it. (10061)"
# EXAMPLE "failed" ERRORS:
# 1. "failed to authenticate to <IP>:<PORT>"
# 2. "cannot connect to <IP>:<PORT>: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (10060)" [!!! this error contains both 'failed' and 'cannot' keywords, but 'failed' keyword is checked first]
echo "Connected via ADB to WiFi device"
echo ""
connected="1"
echo "connected: true"
else
connected="0"
echo "connected: false"
usb_connection
# shouldn't reach this...
fi
else
if [ "${status#*cannot}" != "${status}" ]; then
# posix trick to determine if status contains word "cannot"
echo "Could not connect via ADB to any automatically detected WiFi device"
# EXAMPLE "cannot" ERRORS:
# 1. "cannot connect to <wlan0_IP>:5555: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (10060)"
# 2. "cannot resolve host 'null' and port 5555: No such host is known. (11001)"
# 3. "cannot connect to <IP>:5555: No connection could be made because the target machine actively refused it. (10061)"
connected="0"
echo "connected: false"
try_last_known_device
else
echo "Connected via ADB to WiFi device"
echo ""
connected="1"
echo "connected: true"
fi
fi
fi
echo ""
echo "socket: ${socket}"
echo "connected: ${connected}"
echo ""
if [ ${connected} = 1 ] && [ -n "${socket}" ] && [ "${socket}" != "null" ]; then
# (device is already attached via (tcp/wifi)). Case (wifi 1 ; usb 0) OR (wifi 1 ; usb 1)
# WARNING! there is a bug that after being disconnected, still appears in devices list
device=${socket}
echo "device: ${device}"
echo "connected device: ${device}" >"${debug_log}"
# check if device is rooted
check_root "${device}"
# if device is not rooted
if [ "${rooted}" = 0 ]; then
echo "Device not rooted. Will skip setting permanent props to allow WiFi connectivity through ADB unnatended"
echo ""
ethernally
else
# device rooted
adb -s "${socket}" shell su --command "getprop ro.product.model" >/dev/null
# try to get adb daemon version on android through wifi only . return "error: closed" in case it cannot run the command
exitCode="$?"
# echo "exitCode: ${exitCode}"
if [ ${exitCode} = 0 ]; then
# wifi shell command succeded
# No need to plug USB cable
# Set props
adb -s "${socket}" shell su --command "setprop persist.adb.tcp.port ${port}" &&
printf "Property persist.adb.tcp.port was set to: " &&
adb -s "${socket}" shell su --command "getprop persist.adb.tcp.port" && # set adbd persistent(boot) tcp port
echo ""
ethernally
else
# wifi shell command failed for some reason.
echo "WiFi shell command failed."
# skip to USB
usb_connection
ethernally
fi
fi
else
# cases: (wifi 0 ; usb 0) OR (wifi 0 ; USB 1)
echo ""
echo "Wi-Fi seems to be turned off or ADB debugging not enabled on device."
echo "Could not connect via WiFi, switching to USB mode"
usb_connection
ethernally
fi
##################################
# Notes:
## To reproduce failed with "unauthorized" scenario:
# adb devices # should show "<socket> device"
# 'Revoke USB debugging authorizations' from device's 'Developer Options'
# adb disconnect
# adb connect <socket> # will show "failed to authenticate to <socket>" and also a popup will appear on the device to "Allow USB debugging" for the computer's RSA key fingerprint.
# adb connect <socket> # will show "already connected to <socket>"
# adb devices # will show "<socket> unauthorized"