Tampilkan postingan dengan label notification. Tampilkan semua postingan
Tampilkan postingan dengan label notification. Tampilkan semua postingan

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




remove battery fully charged notification icon and sound

perhaps this is one of the most annoying issues, i cannot understand why we need two icons on the status bar if the battery is fully charged

although there are some how-to already, i wanna show you an alternative way to do it
here is an simplier way to remove the icon (plus the notification sound and screen on when the battery is fully charged if you want to). you can opt to disable all of them, or with any one of them enabled only

*this is for DEODEXED files ONLY!! tested on Android 2.3 KI8 and should work with other versions also


- decompile SystemUI.apk
- open StatusBarPolicy.smali under smali/com/android/systemui/statusbar/policy directory with your favorite text editor
- search for ".method private addFullChargeNotification()V" without quotes
- scroll down a bit and you will find something like:

.line 2300
new-instance v2, Landroid/app/Notification;

const v3, 0x7f02002a

const-wide/16 v4, 0x0

invoke-direct {v2, v3, v1, v4, v5}, Landroid/app/Notification;->(ILjava/lang/CharSequence;J)V

.line 2301
iget v3, v2, Landroid/app/Notification;->flags:I

or-int/lit8 v3, v3, 0x2

iput v3, v2, Landroid/app/Notification;->flags:I

those ".line xxxx" above should be different with yours, and
0x7f02002a is the ID of the battery full icon, you may find it differs and that's fine


for the tweak:

option 1 - replace 0x7f02002a with 0x0

for example, before change:
const v3, 0x7f02002a

after change:
const v3, 0x0


option 2 - add a hash sign (#) before the line const v3, 0x7f02002a and write a new line below it, just in case you want to roll it back

for example, before change:
const v3, 0x7f02002a

after change:
#const v3, 0x7f02002a
const v3, 0x0


also note that the number of hash signs or empty spaces before the line are NOT important!! so all of the lines below are valid:

# const v3, 0x7f02002a
# # const v3, 0x7f02002a
##### const v3, 0x7f02002a




how does this work?

after reading the souce code of Notification.smali, i found that it accepts notification without an icon by calling it with the icon parameter with a zero (which is the 0x0 above)



remove notification sound and screen on
in case you want to remove the notification sound as well, scroll down a bit more and put a # in front of the line as below:

# invoke-direct {p0, v0}, Lcom/android/systemui/statusbar/policy/StatusBarPolicy;->playTone(Landroid/net/Uri;)V



and for the screen on after fully charged, make these changes below the playTone found in above:

# .line 2308
# invoke-direct {p0}, Lcom/android/systemui/statusbar/policy/StatusBarPolicy;->turnOnScreenWithForce()V



to see the result, upload the recompiled SystemUI.apk to /system/app/, and type in adb (no need to reboot/wipe, etc):

kill -HUP `pidof system_server`


and you should notice the changes immediately