Skip to content

Commit 6409dce

Browse files
authored
Merge pull request #34 from bpmct/fix/connectivity-race-no-sleep
Fix/connectivity race no sleep
2 parents 9545ce8 + 6f85d38 commit 6409dce

1 file changed

Lines changed: 58 additions & 6 deletions

File tree

src/com/bpmct/trmnl_nook_simple_touch/DisplayActivity.java

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ protected void onCreate(Bundle savedInstanceState) {
106106

107107
// Initialize file logging from saved preference
108108
FileLogger.setEnabled(ApiPrefs.isFileLoggingEnabled(this));
109+
logD("onCreate pid=" + android.os.Process.myPid()
110+
+ " allow_sleep=" + ApiPrefs.isAllowSleep(this)
111+
+ " super_sleep=" + ApiPrefs.isSuperSleep(this)
112+
+ " auto_disable_wifi=" + ApiPrefs.isAutoDisableWifi(this)
113+
+ " allow_http=" + ApiPrefs.isAllowHttp(this));
109114

110115
// Write the generic screensaver on first-ever launch so NOOK shows something
111116
// branded if it sleeps before any API image has been displayed.
@@ -372,6 +377,9 @@ public void onReceive(Context context, Intent intent) {
372377
@Override
373378
protected void onResume() {
374379
super.onResume();
380+
logD("onResume pid=" + android.os.Process.myPid()
381+
+ " fetchInProgress=" + fetchInProgress
382+
+ " wifi=" + getWifiStateString());
375383
getWindow().setFlags(
376384
WindowManager.LayoutParams.FLAG_FULLSCREEN,
377385
WindowManager.LayoutParams.FLAG_FULLSCREEN);
@@ -399,6 +407,8 @@ protected void onResume() {
399407
} else {
400408
startFetch();
401409
}
410+
} else {
411+
logD("onResume: fetch already in progress, skipping");
402412
}
403413
// Don't schedule here - fetch completion will schedule the next refresh
404414
}
@@ -460,7 +470,14 @@ public void run() {
460470
@Override
461471
public void run() {
462472
pendingConnectivityTimeoutRunnable = null;
463-
logD("connectivity wait timed out");
473+
WifiManager wm = (WifiManager) a.getSystemService(Context.WIFI_SERVICE);
474+
String wifiDetail = "unknown";
475+
if (wm != null) {
476+
wifiDetail = "enabled=" + wm.isWifiEnabled();
477+
WifiInfo wi = wm.getConnectionInfo();
478+
if (wi != null) wifiDetail += " ip=" + wi.getIpAddress() + " rssi=" + wi.getRssi();
479+
}
480+
logD("connectivity wait timed out after " + (CONNECTIVITY_MAX_WAIT_MS / 1000L) + "s wifi=" + wifiDetail);
464481
logD("Ensure you are connected to WiFi. Press the home button and go into settings to configure.");
465482
cancelConnectivityWait();
466483
if (showErrorInMenu) {
@@ -551,6 +568,7 @@ private void applyIntentState(Intent intent) {
551568
@Override
552569
protected void onPause() {
553570
super.onPause();
571+
logD("onPause pid=" + android.os.Process.myPid() + " fetchInProgress=" + fetchInProgress);
554572
// Restore screen timeout whenever we leave — user is navigating around the device.
555573
try {
556574
android.provider.Settings.System.putInt(
@@ -560,6 +578,7 @@ protected void onPause() {
560578
} catch (Throwable t) { /* ignore */ }
561579
if (refreshRunnable != null) {
562580
refreshHandler.removeCallbacks(refreshRunnable);
581+
logD("onPause: refresh timer cancelled (fetchInProgress=" + fetchInProgress + ")");
563582
}
564583
if (pendingSleepRunnable != null) {
565584
refreshHandler.removeCallbacks(pendingSleepRunnable);
@@ -582,6 +601,7 @@ protected void onPause() {
582601

583602
@Override
584603
protected void onDestroy() {
604+
logD("onDestroy pid=" + android.os.Process.myPid());
585605
cancelConnectivityWait();
586606
// Safety net: always restore screen timeout in case the app dies before onResume
587607
try {
@@ -718,6 +738,23 @@ private static boolean isConnectedToNetwork(Context context) {
718738
return mobile != null && mobile.isConnected();
719739
}
720740

741+
/**
742+
* Returns true if it is safe to attempt a fetch immediately:
743+
* - ConnectivityManager reports connected (normal case), OR
744+
* - WiFi is enabled and already has an IP address (handles the Android 2.1
745+
* race where isConnected() lags behind actual DHCP/association state).
746+
*
747+
* Only returns false if WiFi is off or has no IP — i.e. we genuinely need
748+
* to wait before the network is usable.
749+
*/
750+
private static boolean isWifiReadyOrConnected(Context context) {
751+
if (isConnectedToNetwork(context)) return true;
752+
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
753+
if (wm == null || !wm.isWifiEnabled()) return false;
754+
WifiInfo info = wm.getConnectionInfo();
755+
return info != null && info.getIpAddress() != 0;
756+
}
757+
721758
/** Write bundled generic_display.jpg to screensaver path. Used as fallback when no API image has been displayed yet. */
722759
private void writeGenericScreensaver() {
723760
Bitmap b = null;
@@ -738,7 +775,14 @@ private void writeScreenshotToScreensaver(Bitmap bitmap) {
738775
int lastSlash = dirPath.lastIndexOf('/');
739776
if (lastSlash >= 0) dirPath = dirPath.substring(0, lastSlash);
740777
try {
741-
new File(dirPath).mkdirs();
778+
File dir = new File(dirPath);
779+
if (!dir.exists()) {
780+
boolean created = dir.mkdirs();
781+
if (!created) {
782+
logW("screensaver mkdir failed (skipping write): " + dirPath);
783+
return;
784+
}
785+
}
742786
} catch (Throwable t) {
743787
logW("screensaver mkdir: " + t);
744788
}
@@ -749,7 +793,8 @@ private void writeScreenshotToScreensaver(Bitmap bitmap) {
749793
out.close();
750794
logD("screensaver written: " + path);
751795
} catch (Throwable t) {
752-
logW("screensaver write failed: " + t);
796+
logW("screensaver write failed: " + path + " — " + t
797+
+ " (dir exists=" + new File(dirPath).exists() + ")");
753798
}
754799
}
755800

@@ -788,14 +833,20 @@ private void startFetch() {
788833
refreshHandler.removeCallbacks(pendingSleepRunnable);
789834
pendingSleepRunnable = null;
790835
}
791-
// Always wait for WiFi before attempting fetch
792-
if (!isConnectedToNetwork(this)) {
836+
// Only wait for WiFi if it's actually off or has no IP yet.
837+
// If WiFi is enabled and has an IP, proceed directly — isConnectedToNetwork()
838+
// can return false momentarily on Android 2.1 (DHCP state lag) even when the
839+
// radio is fully associated, which would incorrectly send us into the 30s
840+
// connectivity wait and trigger "Couldn't connect" for no real reason.
841+
if (!isWifiReadyOrConnected(this)) {
793842
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
794843
if (wifi != null && !wifi.isWifiEnabled()) {
795844
wifi.setWifiEnabled(true);
796845
}
797846
waitForWifiThenFetch();
798847
return;
848+
} else if (!isConnectedToNetwork(this)) {
849+
logD("wifi has IP but ConnectivityManager not yet connected — proceeding anyway");
799850
}
800851
if (!ensureCredentials()) {
801852
return;
@@ -858,7 +909,8 @@ public void run() {
858909
};
859910
}
860911
refreshHandler.removeCallbacks(refreshRunnable);
861-
logD("next display in " + (refreshMs / 1000L) + "s");
912+
long wakeAt = System.currentTimeMillis() + refreshMs;
913+
logD("next display in " + (refreshMs / 1000L) + "s (at " + new java.util.Date(wakeAt) + ")");
862914
refreshHandler.postDelayed(refreshRunnable, refreshMs);
863915
}
864916

0 commit comments

Comments
 (0)