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

Commit f880e9a7 authored by Rafael Higuera Silva's avatar Rafael Higuera Silva
Browse files

Fix exception crashing euiccService process

Test: make and manual testing
Bug: 325065647
Change-Id: I347d25672a725ff44ca134b2a0356d0c5f171d7f
parent fd8f4cc3
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -215,6 +215,11 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
    public interface GetAvailableMemoryInBytesCommandCallback extends BaseEuiccCommandCallback {
        /** Called when the available memory in bytes lookup has completed. */
        void onGetAvailableMemoryInBytesComplete(long availableMemoryInBytes);
        /**
         * Called when the connected LPA does not implement
         * EuiccService#onGetAvailableMemoryInBytes(int).
         */
        void onUnsupportedOperationExceptionComplete(String message);
    }

    /** Callback class for {@link #getOtaStatus}. */
@@ -789,6 +794,18 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
                                                onCommandEnd(callback);
                                            });
                                        }

                                        @Override
                                        public void onUnsupportedOperationException(
                                                String message) {
                                            sendMessage(CMD_COMMAND_COMPLETE, (Runnable) () -> {
                                                ((GetAvailableMemoryInBytesCommandCallback)
                                                        callback)
                                                        .onUnsupportedOperationExceptionComplete(
                                                            message);
                                                onCommandEnd(callback);
                                            });
                                        }
                                    });
                            break;
                        }
+35 −2
Original line number Diff line number Diff line
@@ -1888,10 +1888,12 @@ public class EuiccController extends IEuiccController.Stub {
        return awaitResult(latch, eidRef);
    }

    private long blockingGetAvailableMemoryInBytesFromEuiccService(int cardId) {
    private long blockingGetAvailableMemoryInBytesFromEuiccService(int cardId)
            throws UnsupportedOperationException {
        CountDownLatch latch = new CountDownLatch(1);
        AtomicReference<Long> memoryRef =
                new AtomicReference<>(EuiccManager.EUICC_MEMORY_FIELD_UNAVAILABLE);
        AtomicReference<Exception> exceptionRef = new AtomicReference();
        mConnector.getAvailableMemoryInBytes(
                cardId,
                new EuiccConnector.GetAvailableMemoryInBytesCommandCallback() {
@@ -1901,12 +1903,25 @@ public class EuiccController extends IEuiccController.Stub {
                        latch.countDown();
                    }

                    @Override
                    public void onUnsupportedOperationExceptionComplete(String message) {
                        exceptionRef.set(new UnsupportedOperationException(message));
                        latch.countDown();
                    }

                    @Override
                    public void onEuiccServiceUnavailable() {
                        latch.countDown();
                    }
                });
        return awaitResult(latch, memoryRef);
        try {
            return awaitResultOrException(latch, memoryRef, exceptionRef);
        } catch (UnsupportedOperationException uoe) {
            throw uoe;
        } catch (Exception e) {
            // Other type of exceptions are not expected here but re-throw in case that happens.
            throw new UnsupportedOperationException(e);
        }
    }

    private @OtaStatus int blockingGetOtaStatusFromEuiccService(int cardId) {
@@ -1956,6 +1971,24 @@ public class EuiccController extends IEuiccController.Stub {
        return resultRef.get();
    }

    private static <T> T awaitResultOrException(
            CountDownLatch latch,
            AtomicReference<T> resultRef,
            AtomicReference<Exception> resultException)
            throws Exception {
        try {
            latch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        if (resultException.get() != null) {
            throw resultException.get();
        }

        return resultRef.get();
    }

    // Returns whether the caller has carrier privilege on the given subscription.
    private boolean checkCarrierPrivilegeInMetadata(DownloadableSubscription subscription,
            String callingPackage) {
+68 −0
Original line number Diff line number Diff line
@@ -153,6 +153,11 @@ public class EuiccConnectorTest extends TelephonyTest {
                        fail("Command should have failed");
                    }

                    @Override
                    public void onUnsupportedOperationExceptionComplete(String message) {
                        fail("Command should have failed");
                    }

                    @Override
                    public void onEuiccServiceUnavailable() {
                        assertTrue("Callback called twice", called.compareAndSet(false, true));
@@ -294,6 +299,11 @@ public class EuiccConnectorTest extends TelephonyTest {
                        availableMemoryInBytesRef.set(availableMemoryInBytes);
                    }

                    @Override
                    public void onUnsupportedOperationExceptionComplete(String message) {
                        fail("Command should have failed");
                    }

                    @Override
                    public void onEuiccServiceUnavailable() {
                        fail("Command should have succeeded");
@@ -303,6 +313,54 @@ public class EuiccConnectorTest extends TelephonyTest {
        assertEquals(AVAILABLE_MEMORY, availableMemoryInBytesRef.get().longValue());
    }

    @Test
    public void testCommandDispatch_forAvailableMemory_unsupportedOperationException()
            throws Exception {
        prepareEuiccApp(
                true /* hasPermission */,
                true /* requiresBindPermission */,
                true /* hasPriority */);
        mConnector = new EuiccConnector(mContext, mLooper.getLooper());
        doAnswer(
                new Answer<Void>() {
                    @Override
                    public Void answer(InvocationOnMock invocation) throws Exception {
                        IGetAvailableMemoryInBytesCallback callback =
                                invocation.getArgument(1);
                        callback.onUnsupportedOperationException("exception message");
                        return null;
                    }
                })
                .when(mEuiccService)
                .getAvailableMemoryInBytes(
                        anyInt(), Mockito.<IGetAvailableMemoryInBytesCallback>any());
        final AtomicReference<String> exceptionRef = new AtomicReference<>();
        mConnector.getAvailableMemoryInBytes(
                CARD_ID,
                new EuiccConnector.GetAvailableMemoryInBytesCommandCallback() {
                    @Override
                    public void onGetAvailableMemoryInBytesComplete(long availableMemoryInBytes) {
                        fail("Command should have failed");
                    }

                    @Override
                    public void onUnsupportedOperationExceptionComplete(String message) {
                        if (exceptionRef.get() != null) {
                            fail("Callback called twice");
                        }
                        exceptionRef.set(message);
                    }

                    @Override
                    public void onEuiccServiceUnavailable() {
                        fail("Command should have succeeded");
                    }
                });
        mLooper.dispatchAll();
        String message = exceptionRef.get();
        assertTrue(message != null && !message.isEmpty());
    }

    @Test
    public void testCommandDispatch_remoteException() throws Exception {
        prepareEuiccApp(true /* hasPermission */, true /* requiresBindPermission */,
@@ -346,6 +404,11 @@ public class EuiccConnectorTest extends TelephonyTest {
                        fail("Command should have failed");
                    }

                    @Override
                    public void onUnsupportedOperationExceptionComplete(String message) {
                        fail("Command should have failed");
                    }

                    @Override
                    public void onEuiccServiceUnavailable() {
                        assertTrue("Callback called twice", called.compareAndSet(false, true));
@@ -401,6 +464,11 @@ public class EuiccConnectorTest extends TelephonyTest {
                        fail("Unexpected command success callback");
                    }

                    @Override
                    public void onUnsupportedOperationExceptionComplete(String message) {
                        fail("Command should have failed");
                    }

                    @Override
                    public void onEuiccServiceUnavailable() {
                        assertTrue("Callback called twice", called.compareAndSet(false, true));
+35 −9
Original line number Diff line number Diff line
@@ -283,7 +283,8 @@ public class EuiccControllerTest extends TelephonyTest {
                false /* hasPhoneState */,
                false /* hasPhoneStatePrivileged */,
                false /* hasCarrierPrivileges */);
        callGetAvailableMemoryInBytes(true /* success */, AVAILABLE_MEMORY, CARD_ID);
        callGetAvailableMemoryInBytes(AvailableMemoryCallbackStatus.SUCCESS,
                AVAILABLE_MEMORY, CARD_ID);
    }

    @Test
@@ -294,7 +295,8 @@ public class EuiccControllerTest extends TelephonyTest {
                false /* hasCarrierPrivileges */);
        assertEquals(
                AVAILABLE_MEMORY,
                callGetAvailableMemoryInBytes(true /* success */, AVAILABLE_MEMORY, CARD_ID));
                callGetAvailableMemoryInBytes(AvailableMemoryCallbackStatus.SUCCESS,
                        AVAILABLE_MEMORY, CARD_ID));
    }

    @Test
@@ -305,7 +307,8 @@ public class EuiccControllerTest extends TelephonyTest {
                false /* hasCarrierPrivileges */);
        assertEquals(
                AVAILABLE_MEMORY,
                callGetAvailableMemoryInBytes(true /* success */, AVAILABLE_MEMORY, CARD_ID));
                callGetAvailableMemoryInBytes(AvailableMemoryCallbackStatus.SUCCESS,
                        AVAILABLE_MEMORY, CARD_ID));
    }

    @Test
@@ -316,7 +319,8 @@ public class EuiccControllerTest extends TelephonyTest {
                true /* hasCarrierPrivileges */);
        assertEquals(
                AVAILABLE_MEMORY,
                callGetAvailableMemoryInBytes(true /* success */, AVAILABLE_MEMORY, CARD_ID));
                callGetAvailableMemoryInBytes(AvailableMemoryCallbackStatus.SUCCESS,
                        AVAILABLE_MEMORY, CARD_ID));
    }

    @Test
@@ -327,7 +331,19 @@ public class EuiccControllerTest extends TelephonyTest {
                false /* hasCarrierPrivileges */);
        assertEquals(
                EuiccManager.EUICC_MEMORY_FIELD_UNAVAILABLE,
                callGetAvailableMemoryInBytes(false /* success */, AVAILABLE_MEMORY, CARD_ID));
                callGetAvailableMemoryInBytes(AvailableMemoryCallbackStatus.UNAVAILABLE,
                        AVAILABLE_MEMORY, CARD_ID));
    }

    @Test
    public void testGetAvailableMemoryInBytes_exception() throws Exception {
        setGetAvailableMemoryInBytesPermissions(
                true /* hasPhoneState */,
                false /* hasPhoneStatePrivileged */,
                false /* hasCarrierPrivileges */);
        assertThrows(UnsupportedOperationException.class, () -> callGetAvailableMemoryInBytes(
                AvailableMemoryCallbackStatus.EXCEPTION,
                AVAILABLE_MEMORY, CARD_ID));
    }

    @Test
@@ -339,7 +355,7 @@ public class EuiccControllerTest extends TelephonyTest {
        assertEquals(
                AVAILABLE_MEMORY,
                callGetAvailableMemoryInBytes(
                        true /* success */,
                        AvailableMemoryCallbackStatus.SUCCESS,
                        AVAILABLE_MEMORY,
                        TelephonyManager.UNSUPPORTED_CARD_ID));
    }
@@ -1937,17 +1953,21 @@ public class EuiccControllerTest extends TelephonyTest {
    }

    private long callGetAvailableMemoryInBytes(
            final boolean success, final long availableMemoryInBytes, int cardId) {
            final AvailableMemoryCallbackStatus status,
            final long availableMemoryInBytes,
            int cardId) {
        doAnswer(
                new Answer<Void>() {
                    @Override
                    public Void answer(InvocationOnMock invocation) throws Exception {
                        EuiccConnector.GetAvailableMemoryInBytesCommandCallback cb =
                                invocation.getArgument(1 /* resultCallback */);
                        if (success) {
                        if (status == AvailableMemoryCallbackStatus.SUCCESS) {
                            cb.onGetAvailableMemoryInBytesComplete(availableMemoryInBytes);
                        } else {
                        } else if (status == AvailableMemoryCallbackStatus.UNAVAILABLE) {
                            cb.onEuiccServiceUnavailable();
                        } else if (status == AvailableMemoryCallbackStatus.EXCEPTION) {
                            cb.onUnsupportedOperationExceptionComplete("exception message");
                        }
                        return null;
                    }
@@ -2229,4 +2249,10 @@ public class EuiccControllerTest extends TelephonyTest {
        }
        return mController.mExtrasIntent;
    }

    public enum AvailableMemoryCallbackStatus {
        SUCCESS,
        EXCEPTION,
        UNAVAILABLE
    }
}