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.Channel; 23 import android.se.omapi.Reader; 24 import android.se.omapi.SEService; 25 import android.se.omapi.SEService.OnConnectedListener; 26 import android.se.omapi.Session; 27 import android.telephony.TelephonyManager; 28 29 import java.util.Timer; 30 import java.util.TimerTask; 31 import java.util.concurrent.Executor; 32 33 import androidx.test.InstrumentationRegistry; 34 import androidx.test.runner.AndroidJUnit4; 35 36 import org.junit.After; 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 41 import static org.junit.Assert.assertNotNull; 42 43 /** 44 * Instrumentation test that allows to get some telephony states. 45 * <p>If TelephonyManager does not exists or is not supported, a test failure will be reported 46 */ 47 @RunWith(AndroidJUnit4.class) 48 public class SimCardUtil { 49 50 private static final String SIM_STATE = "sim_state"; 51 private static final String CARRIER_PRIVILEGES = "has_carried_privileges"; 52 private static final String SECURED_ELEMENT = "has_secured_element"; 53 private static final String SE_SERVICE = "has_se_service"; 54 55 private final long SERVICE_CONNECTION_TIME_OUT = 3000; 56 57 private SEService mSeService; 58 private Object mServiceMutex = new Object(); 59 private Timer mConnectionTimer; 60 private ServiceConnectionTimerTask mTimerTask = new ServiceConnectionTimerTask(); 61 private boolean mConnected = false; 62 private final OnConnectedListener mListener = new OnConnectedListener() { 63 @Override 64 public void onConnected() { 65 synchronized (mServiceMutex) { 66 mConnected = true; 67 mServiceMutex.notify(); 68 } 69 } 70 }; 71 72 @Before setUp()73 public void setUp() throws Exception { 74 mSeService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener); 75 mConnectionTimer = new Timer(); 76 mConnectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT); 77 } 78 79 @Test getSimCardInformation()80 public void getSimCardInformation() throws Exception { 81 // Context of the app under test. 82 Context context = InstrumentationRegistry.getTargetContext(); 83 Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 84 85 TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 86 assertNotNull(tm); 87 88 Bundle returnBundle = new Bundle(); 89 // Sim card - SIM_STATE_READY 5 90 int state = tm.getSimState(); 91 returnBundle.putInt(SIM_STATE, state); 92 93 // UICC check 94 boolean carrierPrivileges = tm.hasCarrierPrivileges(); 95 returnBundle.putBoolean(CARRIER_PRIVILEGES, carrierPrivileges); 96 97 // Secured element check 98 if (waitForConnection()) { 99 Reader[] readers = mSeService.getReaders(); 100 for (Reader reader : readers) { 101 returnBundle.putBoolean(SECURED_ELEMENT, reader.isSecureElementPresent()); 102 returnBundle.putBoolean(SE_SERVICE, reader.getSEService() != null ? true : false); 103 } 104 } else { 105 returnBundle.putBoolean(SECURED_ELEMENT, false); 106 returnBundle.putBoolean(SE_SERVICE, false); 107 } 108 SendToInstrumentation.sendBundle(instrumentation, returnBundle); 109 } 110 111 @After tearDown()112 public void tearDown() throws Exception { 113 if (mSeService != null && mSeService.isConnected()) { 114 mSeService.shutdown(); 115 mConnected = false; 116 } 117 } 118 waitForConnection()119 private boolean waitForConnection() { 120 synchronized (mServiceMutex) { 121 if (!mConnected) { 122 try { 123 mServiceMutex.wait(); 124 } catch (InterruptedException e) { 125 return false; 126 } 127 } 128 if (!mConnected) { 129 return false; 130 } 131 if (mConnectionTimer != null) { 132 mConnectionTimer.cancel(); 133 } 134 return true; 135 } 136 } 137 138 private class SynchronousExecutor implements Executor { execute(Runnable r)139 public void execute(Runnable r) { 140 r.run(); 141 } 142 } 143 144 private class ServiceConnectionTimerTask extends TimerTask { 145 @Override run()146 public void run() { 147 synchronized (mServiceMutex) { 148 mServiceMutex.notifyAll(); 149 } 150 } 151 } 152 } 153