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

Commit 13681618 authored by Yoshiaki Naka's avatar Yoshiaki Naka
Browse files

Avoid ANR due to no response to getForbiddenPlmns()

Pending response message for getForbiddenPlmns() can be left in HashMap
when no data or exception is returned by the lower layer. Response shall
always be made regardless of the result of the RIL command in order to
avoid ANR issue in the application layer.

Bug: 143184103
Test: Confirmed the expected response in manual test.

Change-Id: I282378930a0cc6e0e30c11621b3513edab7bab81
parent de110840
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -1193,7 +1193,6 @@ public class SIMRecords extends IccRecords {
                    data = (byte[]) ar.result;
                    if (ar.exception != null || data == null) {
                        loge("Failed getting Forbidden PLMNs: " + ar.exception);
                        break;
                    } else {
                        mFplmns = parseBcdPlmnList(data, "Forbidden");
                    }
@@ -1203,8 +1202,12 @@ public class SIMRecords extends IccRecords {
                        int key = msg.arg2;
                        Message response = retrievePendingTransaction(key).first;
                        if (response != null) {
                            AsyncResult.forMessage(
                                    response, Arrays.copyOf(mFplmns, mFplmns.length), null);
                            if (ar.exception == null && data != null && mFplmns != null) {
                                AsyncResult.forMessage(response, Arrays.copyOf(mFplmns,
                                        mFplmns.length), null);
                            } else {
                                AsyncResult.forMessage(response, null, ar.exception);
                            }
                            response.sendToTarget();
                        } else {
                            loge("Failed to retrieve a response message for FPLMN");
+115 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.internal.telephony.uicc;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.eq;
@@ -31,6 +33,7 @@ import android.os.test.TestLooper;

import androidx.test.runner.AndroidJUnit4;

import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.TelephonyTest;

@@ -171,4 +174,116 @@ public class SIMRecordsTest extends TelephonyTest {
            .when(mFhMock)
            .updateEFTransparent(anyInt(), any(byte[].class), any(Message.class));
    }

    @Test
    public void testGetForbiddenPlmns() {
        doAnswer(
            invocation -> {
                Message response = invocation.getArgument(1);
                byte[] encodedFplmn = IccUtils.encodeFplmns(SHORT_FPLMNS_LIST, EF_SIZE);
                AsyncResult.forMessage(response, encodedFplmn, null);
                response.sendToTarget();
                return null;
            })
            .when(mFhMock)
            .loadEFTransparent(eq(SIMRecords.EF_FPLMN), any(Message.class));

        Message message = Message.obtain(mTestHandler);
        mSIMRecordsUT.getForbiddenPlmns(message);
        mTestLooper.dispatchAll();

        AsyncResult ar = (AsyncResult) message.obj;
        assertNull(ar.exception);
        assertEquals(SHORT_FPLMNS_LIST.toArray(new String[SHORT_FPLMNS_LIST.size()]),
                (String[]) ar.result);
    }

    @Test
    public void testGetForbiddenPlmnsException() {
        doAnswer(
            invocation -> {
                Message response = invocation.getArgument(1);
                AsyncResult.forMessage(response, null, new CommandException(
                        CommandException.Error.OPERATION_NOT_ALLOWED));
                response.sendToTarget();
                return null;
            })
            .when(mFhMock)
            .loadEFTransparent(eq(SIMRecords.EF_FPLMN), any(Message.class));

        Message message = Message.obtain(mTestHandler);
        mSIMRecordsUT.getForbiddenPlmns(message);
        mTestLooper.dispatchAll();

        AsyncResult ar = (AsyncResult) message.obj;
        assertTrue(ar.exception instanceof CommandException);
        assertTrue(((CommandException) ar.exception).getCommandError() ==
                CommandException.Error.OPERATION_NOT_ALLOWED);
        assertNull(ar.result);
    }

    @Test
    public void testGetForbiddenPlmnsNull() {
        doAnswer(
            invocation -> {
                Message response = invocation.getArgument(1);
                AsyncResult.forMessage(response);
                response.sendToTarget();
                return null;
            })
            .when(mFhMock)
            .loadEFTransparent(eq(SIMRecords.EF_FPLMN), any(Message.class));

        Message message = Message.obtain(mTestHandler);
        mSIMRecordsUT.getForbiddenPlmns(message);
        mTestLooper.dispatchAll();

        AsyncResult ar = (AsyncResult) message.obj;
        assertNull(ar.exception);
        assertNull(ar.result);
    }

    @Test
    public void testGetForbiddenPlmnsEmptyList() {
        doAnswer(
            invocation -> {
                Message response = invocation.getArgument(1);
                byte[] encodedFplmn = IccUtils.encodeFplmns(EMPTY_FPLMN_LIST, EF_SIZE);
                AsyncResult.forMessage(response, encodedFplmn, null);
                response.sendToTarget();
                return null;
            })
            .when(mFhMock)
            .loadEFTransparent(eq(SIMRecords.EF_FPLMN), any(Message.class));

        Message message = Message.obtain(mTestHandler);
        mSIMRecordsUT.getForbiddenPlmns(message);
        mTestLooper.dispatchAll();

        AsyncResult ar = (AsyncResult) message.obj;
        assertNull(ar.exception);
        assertEquals(EMPTY_FPLMN_LIST.toArray(new String[EMPTY_FPLMN_LIST.size()]),
                (String[]) ar.result);
    }

    @Test
    public void testGetForbiddenPlmnsInvalidLength() {
        doAnswer(
            invocation -> {
                Message response = invocation.getArgument(1);
                AsyncResult.forMessage(response, new byte[] { (byte) 0xFF, (byte) 0xFF }, null);
                response.sendToTarget();
                return null;
            })
            .when(mFhMock)
            .loadEFTransparent(eq(SIMRecords.EF_FPLMN), any(Message.class));

        Message message = Message.obtain(mTestHandler);
        mSIMRecordsUT.getForbiddenPlmns(message);
        mTestLooper.dispatchAll();

        AsyncResult ar = (AsyncResult) message.obj;
        assertNull(ar.exception);
        assertNull(ar.result);
    }
}