1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.telephony.utility; 17 18 import android.app.Instrumentation; 19 import android.content.Context; 20 import android.device.collectors.util.SendToInstrumentation; 21 import android.os.Bundle; 22 import android.se.omapi.Reader; 23 import android.se.omapi.SEService; 24 import android.se.omapi.SEService.OnConnectedListener; 25 import android.telephony.TelephonyManager; 26 27 import java.util.Timer; 28 import java.util.TimerTask; 29 import java.util.concurrent.Executor; 30 31 import androidx.test.InstrumentationRegistry; 32 import androidx.test.runner.AndroidJUnit4; 33 34 import org.junit.After; 35 import org.junit.Before; 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 import static org.junit.Assert.assertNotNull; 40 41 /** 42 * Instrumentation test that allows to get some telephony states. 43 * <p>If TelephonyManager does not exists or is not supported, a test failure will be reported 44 */ 45 @RunWith(AndroidJUnit4.class) 46 public class SimCardUtil { 47 48 private static final String SIM_STATE = "sim_state"; 49 private static final String CARRIER_PRIVILEGES = "has_carried_privileges"; 50 private static final String SECURED_ELEMENT = "has_secured_element"; 51 private static final String SE_SERVICE = "has_se_service"; 52 53 private static final long SERVICE_CONNECTION_TIME_OUT = 3000; 54 55 private SEService mSeService; 56 private Object mServiceMutex = new Object(); 57 private Timer mConnectionTimer; 58 private ServiceConnectionTimerTask mTimerTask = new ServiceConnectionTimerTask(); 59 private boolean mConnected = false; 60 private final OnConnectedListener mListener = new OnConnectedListener() { 61 @Override 62 public void onConnected() { 63 synchronized (mServiceMutex) { 64 mConnected = true; 65 mServiceMutex.notify(); 66 } 67 } 68 }; 69 70 @Before setUp()71 public void setUp() throws Exception { 72 mSeService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener); 73 mConnectionTimer = new Timer(); 74 mConnectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT); 75 } 76 77 @Test getSimCardInformation()78 public void getSimCardInformation() throws Exception { 79 // Context of the app under test. 80 Context context = InstrumentationRegistry.getTargetContext(); 81 Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 82 83 TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 84 assertNotNull(tm); 85 86 Bundle returnBundle = new Bundle(); 87 // Sim card - SIM_STATE_READY 5 88 int state = tm.getSimState(); 89 returnBundle.putInt(SIM_STATE, state); 90 91 // UICC check 92 boolean carrierPrivileges = tm.hasCarrierPrivileges(); 93 returnBundle.putBoolean(CARRIER_PRIVILEGES, carrierPrivileges); 94 95 // Secured element check 96 if (waitForConnection()) { 97 Reader[] readers = mSeService.getReaders(); 98 for (Reader reader : readers) { 99 returnBundle.putBoolean(SECURED_ELEMENT, reader.isSecureElementPresent()); 100 returnBundle.putBoolean(SE_SERVICE, reader.getSEService() != null ? true : false); 101 } 102 } else { 103 returnBundle.putBoolean(SECURED_ELEMENT, false); 104 returnBundle.putBoolean(SE_SERVICE, false); 105 } 106 SendToInstrumentation.sendBundle(instrumentation, returnBundle); 107 } 108 109 @After tearDown()110 public void tearDown() throws Exception { 111 if (mSeService != null && mSeService.isConnected()) { 112 mSeService.shutdown(); 113 mConnected = false; 114 } 115 } 116 waitForConnection()117 private boolean waitForConnection() { 118 synchronized (mServiceMutex) { 119 if (!mConnected) { 120 try { 121 mServiceMutex.wait(); 122 } catch (InterruptedException e) { 123 return false; 124 } 125 } 126 if (!mConnected) { 127 return false; 128 } 129 if (mConnectionTimer != null) { 130 mConnectionTimer.cancel(); 131 } 132 return true; 133 } 134 } 135 136 private class SynchronousExecutor implements Executor { 137 @Override execute(Runnable r)138 public void execute(Runnable r) { 139 r.run(); 140 } 141 } 142 143 private class ServiceConnectionTimerTask extends TimerTask { 144 @Override run()145 public void run() { 146 synchronized (mServiceMutex) { 147 mServiceMutex.notifyAll(); 148 } 149 } 150 } 151 } 152