fix Android memory full boot loop soft brick bug
IllegalStateException:
"Cannot broadcast before boot completed"
log:
"Running low on memory. Sending notification"
perhaps this is the most ridiculous bug that annoyed many Android users, especially normal users. if i were not able to find the root cause of this bug, i think i would have to reformat the whole device and start to pray. just can't believe it is still there in Android 4.1.2
what is this about?
during the boot process, the checkMemory function will be called to see if your memory (disk space) is full or nearly full. if this is the case, it will send a "Phone storage is full. Delete some files to free space." notification to the users telling them the device is running out of memory (space). thus, users will be alerted by this notification message which, supposedly, shown as a ticker in the status bar
but for some reasons, all notifications will be "checked" by the verifyBroadcastLocked function before sending to the users by showing a message in the status bar, for instance. the "checking mechanisms" include the status of the device, like whether the phone is booted up already. this is very straight forward since it will be pointness to show any notification if the phone is not booted up yet. these notifications will be dropped or should be queued up and will not be sent to the users until a proper time has come. in this case, screen is on or the home screen (desktop) is drawn could be regarded as a proper time
why is this happening?
if one boots up his device which the memory is neary full, then during the boot process the checkMemory function will send a notification to inform the user about this and logged as "Running low on memory. Sending notification". however, since the device is not booted up yet, the verifyBroadcastLocked function will not allow to send this notification for the reason that the boot process is not yet comlpete and throw an IllegalStateException "Cannot broadcast before boot completed"
when this fatal IllegalStateException is sent by verifyBroadcastLocked and received by the system, the boot process will be crashed. this crash event alerts the system that the previous attempt to boot was a failure, which in turn will try to boot the system again. now the device will begin to boot again and during this second boot, the checkMemory function will send a memory low notification again, followed by another "Cannot broadcast before boot completed" IllegalStateException and hence, a boot loop (some describe as soft brick) is created, as illustrated in a simple flow chart as below:
booting up --> low memory/memory full --> send notification --> notification dropped and IllegalStateException thrown --> failed to boot --> try to boot up again --> booting up --> low memory/memory full ...... --> fail to boot --> try to boot up again ......
so if your phone enters a boot loop for unknown reason, try to take a look at the log. if you find something like "Cannot broadcast before boot completed" or "Running low on memory. Sending notification" in the log file, you will know why and how to solve it
how to solve this problem?
1/. always keep an eye on your phone and make sure you have "sufficient" memory (disk space). unfortunately, the word "sufficient" is defined by Google, the programmers, the manufacturers, etc, which could be 2%, 5%, 10% of the total available memory, and can be different in different Android versions, different firmware versions, etc
2/. modify the sending low memory notifications process by:
a) removing sendNotification in checkMemory function in DeviceStorageMonitorService
b) handling the IllegalStateException thrown by verifyBroadcastLocked in ActivityManagerService in a better way
for me, i opted to disable the sendNotification in DeviceStorageMonitorService.smali found inside services.jar as temporary solution. here's how to (based on stock I9300XXELKC):
[i] find the lines that read like:
const-string v2, "DeviceStorageMonitorService"
const-string v3, "Running low on memory. Sending notification"
[ii] remark the following lines a few lines after [i] (line 229 and 230 in my case, may be differnet for you):
### low memory --> boot loop bug --> Cannot broadcast before boot completed
.line 229
#invoke-direct {p0}, Lcom/android/server/DeviceStorageMonitorService;->sendNotification()V
.line 230
#iput-boolean v7, p0, Lcom/android/server/DeviceStorageMonitorService;->mLowMemFlag:Z
by commenting or removing these lines, no memory full notification will be sent but a log will be printed to the system log, and the memory full boot loop bug can be avoided
"Cannot broadcast before boot completed"
log:
"Running low on memory. Sending notification"
perhaps this is the most ridiculous bug that annoyed many Android users, especially normal users. if i were not able to find the root cause of this bug, i think i would have to reformat the whole device and start to pray. just can't believe it is still there in Android 4.1.2
what is this about?
during the boot process, the checkMemory function will be called to see if your memory (disk space) is full or nearly full. if this is the case, it will send a "Phone storage is full. Delete some files to free space." notification to the users telling them the device is running out of memory (space). thus, users will be alerted by this notification message which, supposedly, shown as a ticker in the status bar
but for some reasons, all notifications will be "checked" by the verifyBroadcastLocked function before sending to the users by showing a message in the status bar, for instance. the "checking mechanisms" include the status of the device, like whether the phone is booted up already. this is very straight forward since it will be pointness to show any notification if the phone is not booted up yet. these notifications will be dropped or should be queued up and will not be sent to the users until a proper time has come. in this case, screen is on or the home screen (desktop) is drawn could be regarded as a proper time
why is this happening?
if one boots up his device which the memory is neary full, then during the boot process the checkMemory function will send a notification to inform the user about this and logged as "Running low on memory. Sending notification". however, since the device is not booted up yet, the verifyBroadcastLocked function will not allow to send this notification for the reason that the boot process is not yet comlpete and throw an IllegalStateException "Cannot broadcast before boot completed"
when this fatal IllegalStateException is sent by verifyBroadcastLocked and received by the system, the boot process will be crashed. this crash event alerts the system that the previous attempt to boot was a failure, which in turn will try to boot the system again. now the device will begin to boot again and during this second boot, the checkMemory function will send a memory low notification again, followed by another "Cannot broadcast before boot completed" IllegalStateException and hence, a boot loop (some describe as soft brick) is created, as illustrated in a simple flow chart as below:
booting up --> low memory/memory full --> send notification --> notification dropped and IllegalStateException thrown --> failed to boot --> try to boot up again --> booting up --> low memory/memory full ...... --> fail to boot --> try to boot up again ......
so if your phone enters a boot loop for unknown reason, try to take a look at the log. if you find something like "Cannot broadcast before boot completed" or "Running low on memory. Sending notification" in the log file, you will know why and how to solve it
how to solve this problem?
1/. always keep an eye on your phone and make sure you have "sufficient" memory (disk space). unfortunately, the word "sufficient" is defined by Google, the programmers, the manufacturers, etc, which could be 2%, 5%, 10% of the total available memory, and can be different in different Android versions, different firmware versions, etc
2/. modify the sending low memory notifications process by:
a) removing sendNotification in checkMemory function in DeviceStorageMonitorService
b) handling the IllegalStateException thrown by verifyBroadcastLocked in ActivityManagerService in a better way
for me, i opted to disable the sendNotification in DeviceStorageMonitorService.smali found inside services.jar as temporary solution. here's how to (based on stock I9300XXELKC):
[i] find the lines that read like:
const-string v2, "DeviceStorageMonitorService"
const-string v3, "Running low on memory. Sending notification"
[ii] remark the following lines a few lines after [i] (line 229 and 230 in my case, may be differnet for you):
### low memory --> boot loop bug --> Cannot broadcast before boot completed
.line 229
#invoke-direct {p0}, Lcom/android/server/DeviceStorageMonitorService;->sendNotification()V
.line 230
#iput-boolean v7, p0, Lcom/android/server/DeviceStorageMonitorService;->mLowMemFlag:Z
by commenting or removing these lines, no memory full notification will be sent but a log will be printed to the system log, and the memory full boot loop bug can be avoided