diff --git a/app/src/main/java/org/mozilla/fenix/perf/ThreadPenaltyDeathWithIgnoresListener.kt b/app/src/main/java/org/mozilla/fenix/perf/ThreadPenaltyDeathWithIgnoresListener.kt index 5383b09707..fe00cfa54e 100644 --- a/app/src/main/java/org/mozilla/fenix/perf/ThreadPenaltyDeathWithIgnoresListener.kt +++ b/app/src/main/java/org/mozilla/fenix/perf/ThreadPenaltyDeathWithIgnoresListener.kt @@ -12,6 +12,7 @@ import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.utils.ManufacturerCodes private const val FCQN_EDM_STORAGE_PROVIDER_BASE = "com.android.server.enterprise.storage.EdmStorageProviderBase" +private const val IDS_CONTROLLER_CLASS = "android.app.IdsController" private const val INSTRUMENTED_HOOKS_CLASS = "com.android.tools.deploy.instrument.InstrumentationHooks" /** @@ -47,7 +48,16 @@ class ThreadPenaltyDeathWithIgnoresListener( private fun shouldViolationBeIgnored(violation: Violation): Boolean = isSamsungLgEdmStorageProviderStartupViolation(violation) || - containsInstrumentedHooksClass(violation) + containsInstrumentedHooksClass(violation) || + isSamsungIdsController(violation) + + private fun isSamsungIdsController(violation: Violation): Boolean { + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1806469 + // When launching in debug on a Galaxy S22+ from Android Studio then we hit a DiskReadViolation + // IdsController doesn't appear in Android code search so we match against it. + // https://cs.android.com/search?q=IdsController + return ManufacturerCodes.isSamsung && violation.stackTrace.any { it.className == IDS_CONTROLLER_CLASS } + } private fun isSamsungLgEdmStorageProviderStartupViolation(violation: Violation): Boolean { // Root issue: https://github.com/mozilla-mobile/fenix/issues/17920 diff --git a/app/src/test/java/org/mozilla/fenix/perf/ThreadPenaltyDeathWithIgnoresListenerTest.kt b/app/src/test/java/org/mozilla/fenix/perf/ThreadPenaltyDeathWithIgnoresListenerTest.kt index 288d345b03..a2e050cafd 100644 --- a/app/src/test/java/org/mozilla/fenix/perf/ThreadPenaltyDeathWithIgnoresListenerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/perf/ThreadPenaltyDeathWithIgnoresListenerTest.kt @@ -48,6 +48,26 @@ class ThreadPenaltyDeathWithIgnoresListenerTest { listener.onThreadViolation(violation) } + @Test + fun `GIVEN we're on a Samsung WHEN provided an IdsController violation THEN it will be ignored and logged`() { + mockkObject(ManufacturerCodes) + every { ManufacturerCodes.isSamsung } returns true + + every { violation.stackTrace } returns getIdsControllerStackTrace() + listener.onThreadViolation(violation) + + verify { logger.debug("Ignoring StrictMode ThreadPolicy violation", violation) } + } + + @Test(expected = RuntimeException::class) + fun `GIVEN we're not on a Samsung WHEN provided an IdsController violation THEN we throw an exception`() { + mockkObject(ManufacturerCodes) + every { ManufacturerCodes.isSamsung } returns false + + every { violation.stackTrace } returns getIdsControllerStackTrace() + listener.onThreadViolation(violation) + } + @Test fun `GIVEN we're on a Samsung WHEN provided the EdmStorageProvider violation THEN it will be ignored and logged`() { mockkObject(ManufacturerCodes) @@ -82,6 +102,9 @@ class ThreadPenaltyDeathWithIgnoresListenerTest { listener.onThreadViolation(null) } + private fun getIdsControllerStackTrace() = + StackTraces.getStackTraceFromLogcat("IdsControllerLogcat.txt") + private fun getEdmStorageProviderStackTrace() = StackTraces.getStackTraceFromLogcat("EdmStorageProviderBaseLogcat.txt") diff --git a/app/src/test/resources/IdsControllerLogcat.txt b/app/src/test/resources/IdsControllerLogcat.txt new file mode 100644 index 0000000000..12ae94b528 --- /dev/null +++ b/app/src/test/resources/IdsControllerLogcat.txt @@ -0,0 +1,32 @@ +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at org.mozilla.fenix.perf.ThreadPenaltyDeathWithIgnoresListener.onThreadViolation(ThreadPenaltyDeathWithIgnoresListener.kt:40) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.os.StrictMode$AndroidBlockGuardPolicy.lambda$onThreadPolicyViolation$1(StrictMode.java:1889) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.os.StrictMode$AndroidBlockGuardPolicy$$ExternalSyntheticLambda0.run(Unknown Source:4) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at java.lang.Thread.run(Thread.java:1012) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1658) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at libcore.io.BlockGuardOs.access(BlockGuardOs.java:74) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at libcore.io.ForwardingOs.access(ForwardingOs.java:128) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ActivityThread$AndroidOs.access(ActivityThread.java:8610) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at java.io.UnixFileSystem.checkAccess(UnixFileSystem.java:281) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at java.io.File.exists(File.java:813) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ContextImpl.ensurePrivateDirExists(ContextImpl.java:790) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ContextImpl.ensurePrivateDirExists(ContextImpl.java:781) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ContextImpl.getPreferencesDir(ContextImpl.java:737) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ContextImpl.getSharedPreferencesPath(ContextImpl.java:975) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ContextImpl.deleteSharedPreferences(ContextImpl.java:716) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.content.ContextWrapper.deleteSharedPreferences(ContextWrapper.java:248) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.IdsController.openIdsWindow(IdsController.java:81) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ActivityThread.scheduleVsyncSS(ActivityThread.java:5409) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:5567) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:54) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2574) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:226) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.os.Looper.loop(Looper.java:313) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:8757) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) +2023-08-02 15:56:27.285 13900-14038 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)