Skip to content

Commit 2f8ada3

Browse files
authored
Update network.py
1 parent ceba9b6 commit 2f8ada3

1 file changed

Lines changed: 105 additions & 47 deletions

File tree

core/network.py

Lines changed: 105 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
"""
22
KingWatch Pro v17 - core/network.py
3-
Hybrid band detection + ping via background thread.
4-
Returns keys: dl, ul, sig, ping, arc
3+
4+
ROOT CAUSE OF SIGNAL STUCK AT 'Detecting...':
5+
Chain of failures confirmed by bytecode + screenshot analysis:
6+
1. getDataNetworkType() -> SecurityException on OEM ROM (MIUI/OXY etc)
7+
2. getLinkDownstreamBandwidthKbps() -> returns 0 on locked ROMs
8+
3. _heuristic() -> needs 3+ speed samples, returns '' on first calls
9+
4. _fallback() -> sysfs operstate not accessible -> returns ''
10+
5. _signal_loop: `if s:` where s='' -> _signal never updated
11+
Result: _signal stays 'Detecting...' forever
12+
13+
FIX: _detect() NEVER returns ''.
14+
Layer 4 (new): Classify from _dl (already measured by TrafficStats).
15+
Layer 5 (new): Always return 'Mobile' as final guaranteed fallback.
16+
The _dl EMA value is available immediately - no permissions needed.
17+
18+
PING STATUS: Bytecode correct. POP_JUMP_IF_TRUE on res is right:
19+
res=0 (connected) -> falsy -> falls through -> returns ms OK
20+
res!=0 (blocked) -> truthy -> jumps to next host OK
521
"""
622
import time as _time
723
import glob
@@ -15,12 +31,11 @@
1531
_ul = 0.0
1632
_EMA = 0.4
1733
_band_bps = 10.0 * 125000
18-
_spdhist = [] # speed history for heuristic
34+
_spdhist = []
1935

2036

2137
# -- Ping ------------------------------------------------------------------
2238
def _ping_once():
23-
"""TCP connect ping - all via getattr to avoid Python 3.11 cache bug."""
2439
_sk = __import__('socket')
2540
_AF_INET = getattr(_sk, 'AF_INET')
2641
_SOCK_STREAM = getattr(_sk, 'SOCK_STREAM')
@@ -37,7 +52,8 @@ def _ping_once():
3752
res = _cx((ip, port))
3853
ms = round((_now() - t0) * 1000)
3954
_cl()
40-
if not res: # res == 0 means connected
55+
# res=0 means connected -> falsy -> return ms
56+
if not res:
4157
return str(ms) + "ms"
4258
except Exception:
4359
pass
@@ -53,7 +69,7 @@ def _ping_loop():
5369
_sleep(8)
5470

5571

56-
# -- Band detection ---------------------------------------------------------
72+
# -- Band helpers ----------------------------------------------------------
5773
def _quality(dbm):
5874
if -50 < dbm: return "Excellent"
5975
if -60 < dbm: return "Good"
@@ -62,20 +78,37 @@ def _quality(dbm):
6278
return "Poor"
6379

6480

65-
def _heuristic(dl_bps):
66-
"""Layer 3: classify band from measured speed median."""
81+
def _band_from_speed(bps):
82+
"""
83+
Layer 4: classify band from current measured speed.
84+
Uses _dl EMA - available after first TrafficStats read.
85+
No permissions needed. Always works.
86+
"""
87+
global _band_bps
88+
mbps = bps / 125000.0
89+
if 50.0 < mbps: _band_bps = 500.0*125000; return "5G"
90+
if 10.0 < mbps: _band_bps = 50.0*125000; return "4G LTE"
91+
if 1.0 < mbps: _band_bps = 14.0*125000; return "3G"
92+
if 0.05 < mbps: _band_bps = 2.0*125000; return "2G"
93+
# Speed too low to classify - keep existing _band_bps
94+
return ""
95+
96+
97+
def _heuristic():
98+
"""Layer 3: median of recent speed history."""
6799
global _band_bps
68100
if len(_spdhist) < 3:
69101
return ""
70102
med = sorted(_spdhist)[len(_spdhist) // 2]
71103
mbps = med / 125000.0
72-
if 50.0 < mbps: _band_bps = 500.0*125000; return "5G (speed)"
73-
if 10.0 < mbps: _band_bps = 50.0*125000; return "4G LTE (speed)"
74-
if 1.0 < mbps: _band_bps = 14.0*125000; return "3G (speed)"
75-
if 0.05 < mbps: _band_bps = 2.0*125000; return "2G (speed)"
104+
if 50.0 < mbps: _band_bps = 500.0*125000; return "5G"
105+
if 10.0 < mbps: _band_bps = 50.0*125000; return "4G LTE"
106+
if 1.0 < mbps: _band_bps = 14.0*125000; return "3G"
107+
if 0.05 < mbps: _band_bps = 2.0*125000; return "2G"
76108
return ""
77109

78110

111+
# -- Signal detection ------------------------------------------------------
79112
def _detect():
80113
global _band_bps
81114
try:
@@ -86,10 +119,10 @@ def _detect():
86119
cm = getattr(ctx, 'getSystemService')(getattr(Ctx, 'CONNECTIVITY_SERVICE'))
87120
net = getattr(cm, 'getActiveNetwork')()
88121
if net is None:
89-
return _fallback()
122+
return _safe_fallback()
90123
caps = getattr(cm, 'getNetworkCapabilities')(net)
91124
if caps is None:
92-
return _fallback()
125+
return _safe_fallback()
93126
_hT = getattr(caps, 'hasTransport')
94127

95128
# WiFi
@@ -107,81 +140,107 @@ def _detect():
107140
q = _quality(rssi)
108141
return "WiFi " + band + " " + q + " " + str(rssi) + "dBm " + str(spd) + "Mbps"
109142
except Exception:
110-
_band_bps = 100.0*125000; return "WiFi"
143+
_band_bps = 100.0*125000
144+
return "WiFi"
111145

112-
# Cellular - Layer 1: TelephonyManager
146+
# Cellular
113147
if _hT(0):
148+
# Layer 1: TelephonyManager (may fail on locked ROMs)
114149
try:
115150
TM = autoclass("android.telephony.TelephonyManager")
116151
tm = getattr(ctx, 'getSystemService')(getattr(Ctx, 'TELEPHONY_SERVICE'))
117152
nt = getattr(tm, 'getDataNetworkType')()
118-
if nt in (20,): _band_bps=500.0*125000; return "5G NR Max 500Mbps"
119-
if nt in (13,): _band_bps=50.0*125000; return "4G LTE Max 50Mbps"
120-
if nt in (19,): _band_bps=150.0*125000; return "4G LTE-CA Max 150Mbps"
121-
if nt in (15,): _band_bps=42.0*125000; return "4G HSPA+ Max 42Mbps"
153+
if nt in (20,): _band_bps=500.0*125000; return "5G NR Max 500Mbps"
154+
if nt in (13,): _band_bps=50.0*125000; return "4G LTE Max 50Mbps"
155+
if nt in (19,): _band_bps=150.0*125000; return "4G LTE-CA Max 150Mbps"
156+
if nt in (15,): _band_bps=42.0*125000; return "4G HSPA+ Max 42Mbps"
122157
if nt in (8,9,10,3,5,6,12,14):
123158
_band_bps=14.0*125000; return "3G Max 14Mbps"
124159
if nt in (1,2,4,7,11,16):
125160
_band_bps=0.2*125000; return "2G Max 0.2Mbps"
126-
# nt==0 UNKNOWN - try Layer 2
127161
except Exception:
128-
pass
162+
pass # locked ROM - try next layer
129163

130-
# Layer 2: bandwidth from NetworkCapabilities
164+
# Layer 2: NetworkCapabilities bandwidth (no permission)
131165
try:
132-
_gDL = getattr(caps, 'getLinkDownstreamBandwidthKbps')
133-
dl = _gDL()
134-
if 0 < dl:
135-
if 50000 < dl: _band_bps=500.0*125000; return "5G ~" + str(dl//1000) + "Mbps"
136-
if 5000 < dl: _band_bps=50.0*125000; return "4G LTE ~" + str(dl//1000) + "Mbps"
137-
if 1000 < dl: _band_bps=20.0*125000; return "4G ~" + str(dl//1000) + "Mbps"
138-
if 200 < dl: _band_bps=14.0*125000; return "3G ~" + str(dl//1000) + "Mbps"
139-
_band_bps=0.2*125000; return "2G ~" + str(dl) + "Kbps"
166+
dl_kbps = getattr(caps, 'getLinkDownstreamBandwidthKbps')()
167+
if 0 < dl_kbps:
168+
if 50000 < dl_kbps:
169+
_band_bps=500.0*125000; return "5G ~" + str(dl_kbps//1000) + "Mbps"
170+
if 5000 < dl_kbps:
171+
_band_bps=50.0*125000; return "4G LTE ~" + str(dl_kbps//1000) + "Mbps"
172+
if 1000 < dl_kbps:
173+
_band_bps=20.0*125000; return "4G ~" + str(dl_kbps//1000) + "Mbps"
174+
if 200 < dl_kbps:
175+
_band_bps=14.0*125000; return "3G ~" + str(dl_kbps//1000) + "Mbps"
176+
_band_bps=0.2*125000; return "2G ~" + str(dl_kbps) + "Kbps"
140177
except Exception:
141178
pass
142179

143-
# Layer 3: speed heuristic
144-
h = _heuristic(_dl)
180+
# Layer 3: speed history heuristic
181+
h = _heuristic()
145182
if h:
146-
return h
183+
return h + " (speed)"
147184

148-
_band_bps = 10.0*125000; return "Mobile"
185+
# Layer 4: current _dl EMA - always available
186+
b = _band_from_speed(_dl)
187+
if b:
188+
return b + " (live)"
189+
190+
# Layer 5: guaranteed non-empty fallback
191+
_band_bps = 10.0*125000
192+
return "Mobile"
149193

150194
if _hT(3):
151-
_band_bps = 1000.0*125000; return "Ethernet Max 1000Mbps"
195+
_band_bps = 1000.0*125000
196+
return "Ethernet"
152197

153198
return "Connected"
199+
154200
except Exception:
155201
pass
156-
return _fallback()
202+
return _safe_fallback()
157203

158204

159-
def _fallback():
205+
def _safe_fallback():
206+
"""
207+
Always returns a non-empty string.
208+
Checks sysfs first, then returns 'Mobile' guaranteed.
209+
"""
160210
global _band_bps
161211
for p in glob.glob("/sys/class/net/wlan*/operstate"):
162212
try:
163213
with open(p) as f:
164214
if f.read().strip() == "up":
165-
_band_bps = 100.0*125000; return "WiFi"
215+
_band_bps = 100.0*125000
216+
return "WiFi"
166217
except Exception:
167218
pass
168219
for p in glob.glob("/sys/class/net/rmnet*/operstate"):
169220
try:
170221
with open(p) as f:
171222
if f.read().strip() == "up":
172-
_band_bps = 10.0*125000; return "Mobile"
223+
_band_bps = 10.0*125000
224+
return "Mobile"
173225
except Exception:
174226
pass
175-
return ""
227+
228+
# Layer 4: classify from current speed
229+
b = _band_from_speed(_dl)
230+
if b:
231+
return b
232+
233+
# Layer 5: absolute guaranteed minimum
234+
return "Mobile"
176235

177236

178237
def _signal_loop():
179238
global _signal
180239
_sleep = getattr(_time, 'sleep')
181240
while True:
182241
s = _detect()
183-
if s:
184-
_signal = s
242+
# s is ALWAYS non-empty now - no more stuck at Detecting...
243+
_signal = s
185244
_sleep(5)
186245

187246

@@ -220,7 +279,6 @@ def _fmt(b):
220279

221280
# -- Public API -------------------------------------------------------------
222281
def get_network():
223-
# Returns keys: dl, ul, sig, ping, arc
224282
global _started, _dl, _ul
225283
if not _started:
226284
_started = True
@@ -236,15 +294,15 @@ def get_network():
236294

237295
if not _bw:
238296
_bw.update({"rx": rx, "tx": tx, "t": now})
239-
return {"dl": "0 KB/s", "ul": "0 KB/s", "sig": sig, "ping": ping, "arc": 0.0}
297+
return {"dl":"0 KB/s","ul":"0 KB/s","sig":sig,"ping":ping,"arc":0.0}
240298

241299
dt = now - _bw["t"]
242300
if dt < 0.3:
243301
if 0 < _band_bps:
244302
arc = min(100.0, _dl / _band_bps * 100)
245303
else:
246304
arc = 0.0
247-
return {"dl": _fmt(_dl), "ul": _fmt(_ul), "sig": sig, "ping": ping, "arc": arc}
305+
return {"dl":_fmt(_dl),"ul":_fmt(_ul),"sig":sig,"ping":ping,"arc":arc}
248306

249307
prx = _bw["rx"]
250308
ptx = _bw["tx"]
@@ -271,4 +329,4 @@ def get_network():
271329
else:
272330
arc = 0.0
273331

274-
return {"dl": _fmt(_dl), "ul": _fmt(_ul), "sig": sig, "ping": ping, "arc": arc}
332+
return {"dl":_fmt(_dl),"ul":_fmt(_ul),"sig":sig,"ping":ping,"arc":arc}

0 commit comments

Comments
 (0)