Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 706633bc authored by Caitlin Cassidy's avatar Caitlin Cassidy
Browse files

[Ongoing Call] Catch a security exception instead of crashing SysUI.

This will mean that the ongoing call chip will stay visible even when
the user is in the calling process. However, this is much better than
crashing SysUI.

Fixes: 216693695
Bug: 216489355
Bug: 216248574
Test: verified starting a call won't crash SysUI even with ag/16659008
in the build.
Test: new unit test

Change-Id: I1108fc6fe01f284364331dd9de57ebe9390d4d78
Merged-In: I1108fc6fe01f284364331dd9de57ebe9390d4d78
parent 9492d508
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -242,8 +242,14 @@ class OngoingCallController @Inject constructor(
     * Sets up an [IUidObserver] to monitor the status of the application managing the ongoing call.
     */
    private fun setUpUidObserver(currentCallNotificationInfo: CallNotificationInfo) {
        try {
            isCallAppVisible = isProcessVisibleToUser(
                iActivityManager.getUidProcessState(currentCallNotificationInfo.uid, null))
                    iActivityManager.getUidProcessState(currentCallNotificationInfo.uid, null)
            )
        } catch (se: SecurityException) {
            Log.e(TAG, "Security exception when trying to get process state: $se")
            return
        }

        if (uidObserver != null) {
            iActivityManager.unregisterUidObserver(uidObserver)
@@ -275,12 +281,17 @@ class OngoingCallController @Inject constructor(
            override fun onUidCachedChanged(uid: Int, cached: Boolean) {}
        }

        try {
            iActivityManager.registerUidObserver(
                uidObserver,
                ActivityManager.UID_OBSERVER_PROCSTATE,
                ActivityManager.PROCESS_STATE_UNKNOWN,
                null
            )
        } catch (se: SecurityException) {
            Log.e(TAG, "Security exception when trying to register uid observer: $se")
            return
        }
    }

    /** Returns true if the given [procState] represents a process that's visible to the user. */
+21 −0
Original line number Diff line number Diff line
@@ -217,6 +217,27 @@ class OngoingCallControllerTest : SysuiTestCase() {
        verify(mockIActivityManager, times(numCalls - 1)).unregisterUidObserver(any())
    }

    /** Regression test for b/216248574. */
    @Test
    fun entryUpdated_getUidProcessStateThrowsException_noCrash() {
        `when`(mockIActivityManager.getUidProcessState(eq(CALL_UID), nullable(String::class.java)))
                .thenThrow(SecurityException())

        // No assert required, just check no crash
        notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
    }

    /** Regression test for b/216248574. */
    @Test
    fun entryUpdated_registerUidObserverThrowsException_noCrash() {
        `when`(mockIActivityManager.registerUidObserver(
            any(), any(), any(), nullable(String::class.java)
        )).thenThrow(SecurityException())

        // No assert required, just check no crash
        notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
    }

    /**
     * If a call notification is never added before #onEntryRemoved is called, then the listener
     * should never be notified.