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

Commit e4e33e20 authored by Rafael Higuera Silva's avatar Rafael Higuera Silva Committed by Android (Google) Code Review
Browse files

Merge "Fix exception crashing euiccService process" into main

parents b0fec2e4 f880e9a7
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
    }
}