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

Commit 165ee750 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Ensure null ConnectionService references don't crash phone.

- Modified Call logic to remove precondition asserts for mConnectionService
in favor of null check and error logging.
- Modify rejectCallAndLog to skip calling reject on the incoming call if it
is already destroyed.  This is due to a call which was ended before the
call filtering completes.

Bug: 31236443
Change-Id: I0f93c65697a1b8e697a49118d642ecffe3dea130
parent cb3a48d0
Loading
Loading
Loading
Loading
+49 −16
Original line number Diff line number Diff line
@@ -1328,8 +1328,6 @@ public class Call implements CreateConnectionResponse {
     */
    @VisibleForTesting
    public void answer(int videoState) {
        Preconditions.checkNotNull(mConnectionService);

        // Check to verify that the call is still in the ringing state. A call can change states
        // between the time the user hits 'answer' and Telecom receives the command.
        if (isRinging("answer")) {
@@ -1342,7 +1340,12 @@ public class Call implements CreateConnectionResponse {
            // that it will work. Instead, we wait until confirmation from the connectino service
            // that the call is in a non-STATE_RINGING state before changing the UI. See
            // {@link ConnectionServiceAdapter#setActive} and other set* methods.
            if (mConnectionService != null) {
                mConnectionService.answer(this, videoState);
            } else {
                Log.e(this, new NullPointerException(),
                        "answer call failed due to null CS callId=%s", getId());
            }
            Log.event(this, Log.Events.REQUEST_ACCEPT);
        }
    }
@@ -1355,16 +1358,20 @@ public class Call implements CreateConnectionResponse {
     */
    @VisibleForTesting
    public void reject(boolean rejectWithMessage, String textMessage) {
        Preconditions.checkNotNull(mConnectionService);

        // Check to verify that the call is still in the ringing state. A call can change states
        // between the time the user hits 'reject' and Telecomm receives the command.
        if (isRinging("reject")) {
            // Ensure video state history tracks video state at time of rejection.
            mVideoStateHistory |= mVideoState;

            if (mConnectionService != null) {
                mConnectionService.reject(this, rejectWithMessage, textMessage);
            } else {
                Log.e(this, new NullPointerException(),
                        "reject call failed due to null CS callId=%s", getId());
            }
            Log.event(this, Log.Events.REQUEST_REJECT);

        }
    }

@@ -1372,10 +1379,13 @@ public class Call implements CreateConnectionResponse {
     * Puts the call on hold if it is currently active.
     */
    void hold() {
        Preconditions.checkNotNull(mConnectionService);

        if (mState == CallState.ACTIVE) {
            if (mConnectionService != null) {
                mConnectionService.hold(this);
            } else {
                Log.e(this, new NullPointerException(),
                        "hold call failed due to null CS callId=%s", getId());
            }
            Log.event(this, Log.Events.REQUEST_HOLD);
        }
    }
@@ -1384,10 +1394,13 @@ public class Call implements CreateConnectionResponse {
     * Releases the call from hold if it is currently active.
     */
    void unhold() {
        Preconditions.checkNotNull(mConnectionService);

        if (mState == CallState.ON_HOLD) {
            if (mConnectionService != null) {
                mConnectionService.unhold(this);
            } else {
                Log.e(this, new NullPointerException(),
                        "unhold call failed due to null CS callId=%s", getId());
            }
            Log.event(this, Log.Events.REQUEST_UNHOLD);
        }
    }
@@ -1441,7 +1454,12 @@ public class Call implements CreateConnectionResponse {

        // If the change originated from an InCallService, notify the connection service.
        if (source == SOURCE_INCALL_SERVICE) {
            if (mConnectionService != null) {
                mConnectionService.onExtrasChanged(this, mExtras);
            } else {
                Log.e(this, new NullPointerException(),
                        "putExtras failed due to null CS callId=%s", getId());
            }
        }
    }

@@ -1471,7 +1489,12 @@ public class Call implements CreateConnectionResponse {

        // If the change originated from an InCallService, notify the connection service.
        if (source == SOURCE_INCALL_SERVICE) {
            if (mConnectionService != null) {
                mConnectionService.onExtrasChanged(this, mExtras);
            } else {
                Log.e(this, new NullPointerException(),
                        "removeExtras failed due to null CS callId=%s", getId());
            }
        }
    }

@@ -1512,7 +1535,12 @@ public class Call implements CreateConnectionResponse {
    }

    void postDialContinue(boolean proceed) {
        if (mConnectionService != null) {
            mConnectionService.onPostDialContinue(this, proceed);
        } else {
            Log.e(this, new NullPointerException(),
                    "postDialContinue failed due to null CS callId=%s", getId());
        }
    }

    void conferenceWith(Call otherCall) {
@@ -1614,7 +1642,12 @@ public class Call implements CreateConnectionResponse {
     * @param extras Associated extras.
     */
    public void sendCallEvent(String event, Bundle extras) {
        if (mConnectionService != null) {
            mConnectionService.sendCallEvent(this, event, extras);
        } else {
            Log.e(this, new NullPointerException(),
                    "sendCallEvent failed due to null CS callId=%s", getId());
        }
    }

    void setParentCall(Call parentCall) {
+10 −1
Original line number Diff line number Diff line
@@ -1693,7 +1693,16 @@ public class CallsManager extends Call.ListenerBase
     * @param incomingCall Incoming call that has been rejected
     */
    private void rejectCallAndLog(Call incomingCall) {
        if (incomingCall.getConnectionService() != null) {
            // Only reject the call if it has not already been destroyed.  If a call ends while
            // incoming call filtering is taking place, it is possible that the call has already
            // been destroyed, and as such it will be impossible to send the reject to the
            // associated ConnectionService.
            incomingCall.reject(false, null);
        } else {
            Log.i(this, "rejectCallAndLog - call already destroyed.");
        }

        // Since the call was not added to the list of calls, we have to call the missed
        // call notifier and the call logger manually.
        // Do we need missed call notification for direct to Voicemail calls?