Loading src/java/com/android/internal/telephony/euicc/EuiccConnector.java +17 −0 Original line number Diff line number Diff line Loading @@ -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}. */ Loading Loading @@ -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; } Loading src/java/com/android/internal/telephony/euicc/EuiccController.java +35 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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) { Loading Loading @@ -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) { Loading tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccConnectorTest.java +68 −0 Original line number Diff line number Diff line Loading @@ -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)); Loading Loading @@ -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"); Loading @@ -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 */, Loading Loading @@ -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)); Loading Loading @@ -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)); Loading tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java +35 −9 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -339,7 +355,7 @@ public class EuiccControllerTest extends TelephonyTest { assertEquals( AVAILABLE_MEMORY, callGetAvailableMemoryInBytes( true /* success */, AvailableMemoryCallbackStatus.SUCCESS, AVAILABLE_MEMORY, TelephonyManager.UNSUPPORTED_CARD_ID)); } Loading Loading @@ -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; } Loading Loading @@ -2229,4 +2249,10 @@ public class EuiccControllerTest extends TelephonyTest { } return mController.mExtrasIntent; } public enum AvailableMemoryCallbackStatus { SUCCESS, EXCEPTION, UNAVAILABLE } } Loading
src/java/com/android/internal/telephony/euicc/EuiccConnector.java +17 −0 Original line number Diff line number Diff line Loading @@ -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}. */ Loading Loading @@ -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; } Loading
src/java/com/android/internal/telephony/euicc/EuiccController.java +35 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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) { Loading Loading @@ -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) { Loading
tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccConnectorTest.java +68 −0 Original line number Diff line number Diff line Loading @@ -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)); Loading Loading @@ -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"); Loading @@ -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 */, Loading Loading @@ -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)); Loading Loading @@ -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)); Loading
tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java +35 −9 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -339,7 +355,7 @@ public class EuiccControllerTest extends TelephonyTest { assertEquals( AVAILABLE_MEMORY, callGetAvailableMemoryInBytes( true /* success */, AvailableMemoryCallbackStatus.SUCCESS, AVAILABLE_MEMORY, TelephonyManager.UNSUPPORTED_CARD_ID)); } Loading Loading @@ -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; } Loading Loading @@ -2229,4 +2249,10 @@ public class EuiccControllerTest extends TelephonyTest { } return mController.mExtrasIntent; } public enum AvailableMemoryCallbackStatus { SUCCESS, EXCEPTION, UNAVAILABLE } }