SUWULLC / Octal

Hacker News Client for iOS
101 stars 2 forks source link

Battery drained by background activity #271

Closed AustinWise closed 1 year ago

AustinWise commented 1 year ago

The battery usage page in the iOS settings showed Octal keeping the "screen off" time at 60m an hour for 6 hours.

image

Please let me know if there is anything I can do to collect more information to help diagnose the problem.

dangwu commented 1 year ago

Let me know if you find anything else out, but I'm confident that Octal doesn't do anything that would cause this. It does not use BackgroundTasks or anything like that at all.

AustinWise commented 1 year ago

I realize that the bug report as is does not point at any obvious cause. So I'm more asking if there is a way I can help root cause this.

I have a hunch that somehow an in-app browser is hanging around after being closed and burning the battery.

One idea is to add some sort of diagnostics. Maybe something as simple as a button to crash the app that results in a crash report being sent to Apple that you can then look at. That way if I notice the app rating battery I can push the button and hopefully the stack traces point to the issue.

timbeccue commented 1 year ago

I'd like to share that this issue has affected me as well. My guess is that it has something to do with the in app safari browser, as I've seen my screen time show 20 hours spent on a url that was opened only in the octal app (for much less time than reported). I also recall this issue draining my battery while my phone was in airplane mode on a flight, and the battery stats showed octal background activity consuming the vast majority of power. I know these details or somewhat vague, but maybe that helps provide some clues.

AustinWise commented 1 year ago

I found a HN story that reproduces the problem:

https://news.ycombinator.com/item?id=35583228

It does not reproduce the problem 100% of the time, but it did enough that I was able to create a recording:

https://storage.googleapis.com/random-files-383906/octal-in-background.mp4

Note that the audio keeps playing after the in-app browser is closed and after returning to the home screen.

dangwu commented 1 year ago

Interesting - thanks for the reports. From that video, Octal is really doing nothing special - just opening the link in SFSafariViewController - an Apple API. I would imagine that this is an iOS bug if anything.

On Tue, May 2, 2023 at 9:52 AM Austin Wise @.***> wrote:

I found a HN story that reproduces the problem:

https://news.ycombinator.com/item?id=35583228

It does not reproduce the problem 100% of the time, but it did enough that I was able to create a recording:

https://storage.googleapis.com/random-files-383906/octal-in-background.mp4

Note that the audio keeps playing after the in-app browser is closed and after returning to the home screen.

— Reply to this email directly, view it on GitHub https://github.com/dangwu/Octal/issues/271#issuecomment-1531815077, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHKY3YGNTCHZJQ44ELSUCLXEE3UJANCNFSM6AAAAAAWNL76JU . You are receiving this because you modified the open/close state.Message ID: @.***>

AustinWise commented 1 year ago

Thanks for the hint about SFSafariViewController. I was able to reproduce the problem in a small iOS project:

https://github.com/AustinWise/OctalWebkitLeakDemo

What I discovered that as long as the SFSafariViewController object is alive, the music will keep playing. If the SFSafariViewController object is released, the music stop playing. To create a leak, I assigned the SFSafariViewController object to a global variable. You see that once you uncomment the ctrl = nil; line, the music stop playing when the Safari view is dismissed.

I'm guessing that somehow Octal is keeping the SFSafariViewController object alive after the Safari view is closed. I don't know much about iOS dev on how to track down this sort of resource leak.

dangwu commented 1 year ago

That’s an excellent find - thank you very much. I can look into this soon. I’m fairly sure I’m not holding into to a SF VC reference more than necessary, but maybe I’m wrong or there’s another way.

On Wed, May 10, 2023 at 6:20 AM Austin Wise @.***> wrote:

Thanks for the hint about SFSafariViewController. I was able to reproduce the problem in a small iOS project:

https://github.com/AustinWise/OctalWebkitLeakDemo

What I discovered that as long as the SFSafariViewController object is alive, the music will keep playing. If the SFSafariViewController object is released, the music stop playing. To create a leak, I assigned the SFSafariViewController object to a global variable. You see that once you uncomment the ctrl = nil; https://github.com/AustinWise/OctalWebkitLeakDemo/blob/10df08ffa872ebea2195315f2b6f7475d83e5095/TestRetain/ViewController.m#LL27C11-L27C11 line, the music stop playing when the Safari view is dismissed.

I'm guessing that somehow Octal is keeping the SFSafariViewController object alive after the Safari view is closed. I don't know much about iOS dev on how to track down this sort of resource leak.

— Reply to this email directly, view it on GitHub https://github.com/dangwu/Octal/issues/271#issuecomment-1541331821, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHKY3YULC4SWNAS3TAXOPLXFMJOPANCNFSM6AAAAAAWNL76JU . You are receiving this because you modified the open/close state.Message ID: @.***>

AustinWise commented 1 year ago

I played around Xcode and instruments a little. When debugging you can launch Instruments:

Screenshot 2023-05-13 at 12 03 46 PM

After you open the web view and close, take a snapshot (or just wait for 10 seconds for a new green check mark). Then search the allocations for SFSafariViewController. Navigate to the specific instance that is still alive by clicking on the memory address. Set "Show" to "Unpaired" and search for the name of your application (TestRetain in my case). You should be able to see the call stack that retained the objective without releasing.

Screenshot 2023-05-13 at 12 03 07 PM
dangwu commented 1 year ago

I checked the code, and I'm not retaining the SFSafariViewController instance. it's simply created and presented via presentingViewController.present(safariViewController, animated: true). And when closed, it's dismissed. The instance is not set to any local variable or anything, so there's nothing to nil-out.

I also used Instruments and verified that the # Persistent count is 1 when presented, and 0 when dismissed. I tested 10 times with different links.

So I'm fairly confident that this is some (rare) internal issue with SFSafariViewController.

AustinWise commented 1 year ago

Thanks for checking. Too bad it was not something simple.