1/* 2 * Copyright (C) 2016 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 */ 16package com.android.internal.telephony; 17 18import android.app.AppOpsManager; 19import android.content.ContentValues; 20import android.content.Intent; 21import android.database.Cursor; 22import android.database.MatrixCursor; 23import android.net.Uri; 24import android.os.Bundle; 25import android.os.UserHandle; 26import android.provider.Settings; 27import android.test.mock.MockContentProvider; 28import android.test.mock.MockContentResolver; 29import android.test.suitebuilder.annotation.SmallTest; 30import static org.junit.Assert.*; 31import static org.mockito.Mockito.*; 32import org.junit.After; 33import org.junit.Before; 34import org.junit.Test; 35import org.mockito.ArgumentCaptor; 36import org.mockito.Mock; 37 38import android.telephony.SubscriptionInfo; 39import android.telephony.SubscriptionManager; 40import android.util.Log; 41 42import java.util.ArrayList; 43import java.util.List; 44 45public class SubscriptionControllerTest extends TelephonyTest { 46 47 private static final int SINGLE_SIM = 1; 48 private String mCallingPackage; 49 private SubscriptionController mSubscriptionControllerUT; 50 private MockContentResolver mMockContentResolver; 51 52 @Mock private List<SubscriptionInfo> mSubList; 53 @Mock private AppOpsManager mAppOps; 54 55 public class FakeSubscriptionContentProvider extends MockContentProvider { 56 57 private ArrayList<ContentValues> mSubscriptionArray = 58 new ArrayList<ContentValues>(); 59 60 private String[] mKeyMappingSet = new String[]{ 61 SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID, 62 SubscriptionManager.ICC_ID, SubscriptionManager.SIM_SLOT_INDEX, 63 SubscriptionManager.DISPLAY_NAME, SubscriptionManager.CARRIER_NAME, 64 SubscriptionManager.NAME_SOURCE, SubscriptionManager.COLOR, 65 SubscriptionManager.NUMBER, SubscriptionManager.DISPLAY_NUMBER_FORMAT, 66 SubscriptionManager.DATA_ROAMING, SubscriptionManager.MCC, 67 SubscriptionManager.MNC, SubscriptionManager.CB_EXTREME_THREAT_ALERT, 68 SubscriptionManager.CB_SEVERE_THREAT_ALERT, SubscriptionManager.CB_AMBER_ALERT, 69 SubscriptionManager.CB_ALERT_SOUND_DURATION, 70 SubscriptionManager.CB_ALERT_REMINDER_INTERVAL, 71 SubscriptionManager.CB_ALERT_VIBRATE, SubscriptionManager.CB_ALERT_SPEECH, 72 SubscriptionManager.CB_ETWS_TEST_ALERT, SubscriptionManager.CB_CHANNEL_50_ALERT, 73 SubscriptionManager.CB_CMAS_TEST_ALERT, SubscriptionManager.CB_OPT_OUT_DIALOG, 74 SubscriptionManager.SIM_PROVISIONING_STATUS}; 75 76 /* internal util function */ 77 private MatrixCursor convertFromContentToCursor(ContentValues initialValues) { 78 MatrixCursor cursor = null; 79 ArrayList<Object> values = new ArrayList<Object>(); 80 81 if (initialValues != null && mKeyMappingSet.length != 0) { 82 cursor = new MatrixCursor(mKeyMappingSet); 83 /* push value from contentValues to matrixCursors */ 84 for (String key : mKeyMappingSet) { 85 if (initialValues.containsKey(key)) { 86 values.add(initialValues.get(key)); 87 } else { 88 values.add(null); 89 } 90 } 91 cursor.addRow(values.toArray()); 92 } 93 return cursor; 94 } 95 96 @Override 97 public int delete(Uri uri, String selection, String[] selectionArgs) { 98 if (mSubscriptionArray.size() > 0) { 99 mSubscriptionArray.remove(0); 100 return 1; 101 } 102 return -1; 103 } 104 105 @Override 106 public Uri insert(Uri uri, ContentValues values) { 107 values.put(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID, 0); 108 mSubscriptionArray.add(values); 109 return uri; 110 } 111 112 @Override 113 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 114 String sortOrder) { 115 if (mSubscriptionArray.size() > 0) { 116 return convertFromContentToCursor(mSubscriptionArray.get(0)); 117 } 118 return null; 119 } 120 121 @Override 122 public Bundle call(String method, String request, Bundle args) { 123 return null; 124 } 125 126 @Override 127 public int update(android.net.Uri uri, android.content.ContentValues values, 128 java.lang.String selection, java.lang.String[] selectionArgs) { 129 if (mSubscriptionArray.size() > 0) { 130 ContentValues val = mSubscriptionArray.get(0); 131 for (String key : values.keySet()) { 132 val.put(key, values.getAsString(key)); 133 Log.d(TAG, "update the values..." + key + "..." + values.getAsString(key)); 134 } 135 mSubscriptionArray.set(0, val); 136 return 1; 137 } 138 return -1; 139 } 140 } 141 142 @Before 143 public void setUp() throws Exception { 144 super.setUp("SubscriptionControllerTest"); 145 146 doReturn(SINGLE_SIM).when(mTelephonyManager).getSimCount(); 147 doReturn(SINGLE_SIM).when(mTelephonyManager).getPhoneCount(); 148 149 replaceInstance(SubscriptionController.class, "sInstance", null, null); 150 151 SubscriptionController.init(mContext, null); 152 mSubscriptionControllerUT = SubscriptionController.getInstance(); 153 mCallingPackage = mContext.getOpPackageName(); 154 155 doReturn(1).when(mProxyController).getMaxRafSupported(); 156 mContextFixture.putIntArrayResource(com.android.internal.R.array.sim_colors, new int[]{5}); 157 158 mSubscriptionControllerUT.getInstance().updatePhonesAvailability(new Phone[]{mPhone}); 159 mMockContentResolver = (MockContentResolver) mContext.getContentResolver(); 160 mMockContentResolver.addProvider(SubscriptionManager.CONTENT_URI.getAuthority(), 161 new FakeSubscriptionContentProvider()); 162 } 163 164 @After 165 public void tearDown() throws Exception { 166 /* should clear fake content provider and resolver here */ 167 mContext.getContentResolver().delete(SubscriptionManager.CONTENT_URI, null, null); 168 169 /* clear settings for default voice/data/sms sub ID */ 170 Settings.Global.putInt(mContext.getContentResolver(), 171 Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION, 172 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 173 Settings.Global.putInt(mContext.getContentResolver(), 174 Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION, 175 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 176 Settings.Global.putInt(mContext.getContentResolver(), 177 Settings.Global.MULTI_SIM_SMS_SUBSCRIPTION, 178 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 179 180 mSubscriptionControllerUT = null; 181 super.tearDown(); 182 } 183 184 @Test @SmallTest 185 public void testInsertSim() { 186 int slotID = mSubscriptionControllerUT.getAllSubInfoCount(mCallingPackage); 187 188 //verify there is no sim inserted in the SubscriptionManager 189 assertEquals(0, slotID); 190 191 //insert one Subscription Info 192 mSubscriptionControllerUT.addSubInfoRecord("test", slotID); 193 194 //verify there is one sim 195 assertEquals(1, mSubscriptionControllerUT.getAllSubInfoCount(mCallingPackage)); 196 197 //sanity for slot id and sub id 198 List<SubscriptionInfo> mSubList = mSubscriptionControllerUT 199 .getActiveSubscriptionInfoList(mCallingPackage); 200 assertTrue(mSubList != null && mSubList.size() > 0); 201 for (int i = 0; i < mSubList.size(); i++) { 202 assertTrue(SubscriptionManager.isValidSubscriptionId( 203 mSubList.get(i).getSubscriptionId())); 204 assertTrue(SubscriptionManager.isValidSlotIndex(mSubList.get(i).getSimSlotIndex())); 205 } 206 } 207 208 @Test @SmallTest 209 public void testChangeSIMProperty() { 210 int dataRoaming = 1; 211 int iconTint = 1; 212 String disName = "TESTING"; 213 String disNum = "12345"; 214 215 testInsertSim(); 216 /* Get SUB ID */ 217 int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(); 218 assertTrue(subIds != null && subIds.length != 0); 219 int subID = subIds[0]; 220 221 /* Setting */ 222 mSubscriptionControllerUT.setDisplayName(disName, subID); 223 mSubscriptionControllerUT.setDataRoaming(dataRoaming, subID); 224 mSubscriptionControllerUT.setDisplayNumber(disNum, subID); 225 mSubscriptionControllerUT.setIconTint(iconTint, subID); 226 227 /* Getting, there is no direct getter function for each fields of property */ 228 SubscriptionInfo subInfo = mSubscriptionControllerUT 229 .getActiveSubscriptionInfo(subID, mCallingPackage); 230 assertNotNull(subInfo); 231 assertEquals(dataRoaming, subInfo.getDataRoaming()); 232 assertEquals(disName, subInfo.getDisplayName()); 233 assertEquals(iconTint, subInfo.getIconTint()); 234 assertEquals(disNum, subInfo.getNumber()); 235 236 /* verify broadcast intent */ 237 ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class); 238 verify(mContext, atLeast(1)).sendBroadcast(captorIntent.capture()); 239 assertEquals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED, 240 captorIntent.getValue().getAction()); 241 } 242 243 @Test @SmallTest 244 public void testCleanUpSIM() { 245 testInsertSim(); 246 assertFalse(mSubscriptionControllerUT.isActiveSubId(1)); 247 mSubscriptionControllerUT.clearSubInfo(); 248 assertFalse(mSubscriptionControllerUT.isActiveSubId(0)); 249 assertEquals(SubscriptionManager.SIM_NOT_INSERTED, 250 mSubscriptionControllerUT.getSlotIndex(0)); 251 } 252 253 @Test @SmallTest 254 public void testDefaultSubID() { 255 assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 256 mSubscriptionControllerUT.getDefaultDataSubId()); 257 assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 258 mSubscriptionControllerUT.getDefaultSmsSubId()); 259 assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 260 mSubscriptionControllerUT.getDefaultSmsSubId()); 261 /* insert one sim */ 262 testInsertSim(); 263 // if support single sim, sms/data/voice default sub should be the same 264 assertNotSame(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 265 mSubscriptionControllerUT.getDefaultSubId()); 266 assertEquals(mSubscriptionControllerUT.getDefaultDataSubId(), 267 mSubscriptionControllerUT.getDefaultSmsSubId()); 268 assertEquals(mSubscriptionControllerUT.getDefaultDataSubId(), 269 mSubscriptionControllerUT.getDefaultVoiceSubId()); 270 } 271 272 @Test @SmallTest 273 public void testSetGetMCCMNC() { 274 testInsertSim(); 275 String mCcMncVERIZON = "310004"; 276 mSubscriptionControllerUT.setMccMnc(mCcMncVERIZON, 0); 277 278 SubscriptionInfo subInfo = mSubscriptionControllerUT 279 .getActiveSubscriptionInfo(0, mCallingPackage); 280 assertNotNull(subInfo); 281 assertEquals(Integer.parseInt(mCcMncVERIZON.substring(0, 3)), subInfo.getMcc()); 282 assertEquals(Integer.parseInt(mCcMncVERIZON.substring(3)), subInfo.getMnc()); 283 284 /* verify broadcast intent */ 285 ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class); 286 verify(mContext, atLeast(1)).sendBroadcast(captorIntent.capture()); 287 assertEquals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED, 288 captorIntent.getValue().getAction()); 289 } 290 291 @Test 292 @SmallTest 293 public void testSetDefaultDataSubId() throws Exception { 294 doReturn(1).when(mPhone).getSubId(); 295 296 mSubscriptionControllerUT.setDefaultDataSubId(1); 297 298 verify(mPhone, times(1)).updateDataConnectionTracker(); 299 ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class); 300 verify(mContext, times(1)).sendStickyBroadcastAsUser( 301 captorIntent.capture(), eq(UserHandle.ALL)); 302 303 Intent intent = captorIntent.getValue(); 304 assertEquals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED, intent.getAction()); 305 306 Bundle b = intent.getExtras(); 307 308 assertTrue(b.containsKey(PhoneConstants.SUBSCRIPTION_KEY)); 309 assertEquals(1, b.getInt(PhoneConstants.SUBSCRIPTION_KEY)); 310 } 311} 312