1 /* 2 * Copyright (C) 2021 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 17 package com.android.imsserviceentitlement; 18 19 import static android.telephony.TelephonyManager.SIM_STATE_LOADED; 20 import static android.telephony.TelephonyManager.SIM_STATE_PIN_REQUIRED; 21 22 import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_EIGHT; 23 import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_TWO; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import static org.mockito.Mockito.never; 28 import static org.mockito.Mockito.times; 29 import static org.mockito.Mockito.verify; 30 import static org.mockito.Mockito.when; 31 32 import android.content.ComponentName; 33 import android.content.Context; 34 import android.content.Intent; 35 import android.content.SharedPreferences; 36 import android.os.PersistableBundle; 37 import android.os.UserManager; 38 import android.provider.Settings; 39 import android.telephony.CarrierConfigManager; 40 import android.telephony.SubscriptionManager; 41 42 import androidx.test.core.app.ApplicationProvider; 43 import androidx.test.runner.AndroidJUnit4; 44 45 import com.android.imsserviceentitlement.entitlement.EntitlementConfiguration; 46 import com.android.imsserviceentitlement.job.JobManager; 47 import com.android.imsserviceentitlement.utils.Executors; 48 import com.android.imsserviceentitlement.utils.TelephonyUtils; 49 50 import org.junit.After; 51 import org.junit.Before; 52 import org.junit.Rule; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.Mock; 56 import org.mockito.Spy; 57 import org.mockito.junit.MockitoJUnit; 58 import org.mockito.junit.MockitoRule; 59 60 import java.lang.reflect.Field; 61 62 @RunWith(AndroidJUnit4.class) 63 public class ImsEntitlementReceiverTest { 64 private static final int SUB_ID = 1; 65 private static final int LAST_SUB_ID = 2; 66 private static final String KEY_ENTITLEMENT_VERSION_INT = 67 "imsserviceentitlement.entitlement_version_int"; 68 private static final String RAW_XML = 69 "<wap-provisioningdoc version=\"1.1\">\n" 70 + " <characteristic type=\"APPLICATION\">\n" 71 + " <parm name=\"AppID\" value=\"ap2004\"/>\n" 72 + " <parm name=\"EntitlementStatus\" value=\"1\"/>\n" 73 + " </characteristic>\n" 74 + "</wap-provisioningdoc>\n"; 75 76 private static final String RAW_XML_VERSION_0_VALIDITY_0 = 77 "<wap-provisioningdoc version=\"1.1\">\n" 78 + " <characteristic type=\"VERS\">\n" 79 + " <parm name=\"version\" value=\"0\"/>\n" 80 + " <parm name=\"validity\" value=\"0\"/>\n" 81 + " </characteristic>\n" 82 + "</wap-provisioningdoc>\n"; 83 84 private static final String RAW_XML_INVALID_VERS = 85 "<wap-provisioningdoc version=\"1.1\">\n" 86 + " <characteristic type=\"VERS\">\n" 87 + " <parm name=\"version\" value=\"-1\"/>\n" 88 + " <parm name=\"validity\" value=\"-1\"/>\n" 89 + " </characteristic>\n" 90 + "</wap-provisioningdoc>\n"; 91 private static final ComponentName POLLING_SERVICE_COMPONENT_NAME = 92 ComponentName.unflattenFromString( 93 "com.android.imsserviceentitlement/.ImsEntitlementPollingService"); 94 95 @Rule public final MockitoRule rule = MockitoJUnit.rule(); 96 97 @Mock private TelephonyUtils mMockTelephonyUtils; 98 @Mock private UserManager mMockUserManager; 99 @Mock private CarrierConfigManager mCarrierConfigManager; 100 @Mock private JobManager mMockJobManager; 101 102 @Spy private final Context mContext = ApplicationProvider.getApplicationContext(); 103 104 private ImsEntitlementReceiver mReceiver; 105 private PersistableBundle mCarrierConfig; 106 private boolean mIsBootUp; 107 108 @Before setUp()109 public void setUp() throws Exception { 110 mReceiver = new ImsEntitlementReceiver() { 111 @Override 112 protected Dependencies createDependency(Context context, int subId) { 113 Dependencies dependencies = new Dependencies(); 114 dependencies.userManager = mMockUserManager; 115 dependencies.telephonyUtils = mMockTelephonyUtils; 116 dependencies.jobManager = mMockJobManager; 117 return dependencies; 118 } 119 120 @Override 121 protected boolean isBootUp(Context context, int slotId) { 122 return mIsBootUp; 123 } 124 }; 125 mIsBootUp = false; 126 127 new EntitlementConfiguration(mContext, LAST_SUB_ID) 128 .update(ENTITLEMENT_VERSION_TWO, RAW_XML); 129 new EntitlementConfiguration(mContext, SUB_ID).reset(); 130 131 when(mMockUserManager.isSystemUser()).thenReturn(true); 132 when(mMockTelephonyUtils.getSimApplicationState()).thenReturn(SIM_STATE_LOADED); 133 134 setLastSubId(LAST_SUB_ID, 0); 135 setImsProvisioningBool(true); 136 useDirectExecutor(); 137 } 138 139 @After tearDown()140 public void tearDown() { 141 mCarrierConfig = null; 142 } 143 144 @Test onReceive_simChanged_dataReset()145 public void onReceive_simChanged_dataReset() { 146 mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 0)); 147 148 assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml()).isEqualTo(null); 149 verify(mMockJobManager, times(1)).queryEntitlementStatusOnceNetworkReady(); 150 } 151 152 @Test onReceive_simChanged_simPinLockedThenLoaded()153 public void onReceive_simChanged_simPinLockedThenLoaded() { 154 // SIM PIN locked 155 when(mMockTelephonyUtils.getSimApplicationState()).thenReturn(SIM_STATE_PIN_REQUIRED); 156 157 mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 0)); 158 159 // no-op 160 assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml()) 161 .isEqualTo(RAW_XML); 162 verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady(); 163 164 // SIM LOADED 165 when(mMockTelephonyUtils.getSimApplicationState()).thenReturn(SIM_STATE_LOADED); 166 167 mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 0)); 168 169 // configuration reset and entitlement query scheduled. 170 assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml()).isEqualTo(null); 171 verify(mMockJobManager, times(1)).queryEntitlementStatusOnceNetworkReady(); 172 } 173 174 @Test onReceive_theSameSim_dataNotReset()175 public void onReceive_theSameSim_dataNotReset() { 176 mReceiver.onReceive( 177 mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0)); 178 179 assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml()) 180 .isEqualTo(RAW_XML); 181 verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady(); 182 } 183 184 @Test onReceive_differentSlot_dataNotReset()185 public void onReceive_differentSlot_dataNotReset() { 186 setLastSubId(LAST_SUB_ID, 1); 187 188 mReceiver.onReceive( 189 mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 1)); 190 191 assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml()) 192 .isEqualTo(RAW_XML); 193 verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady(); 194 } 195 196 @Test onReceive_simChangedAndDifferentSlotId_dataReset()197 public void onReceive_simChangedAndDifferentSlotId_dataReset() { 198 setLastSubId(LAST_SUB_ID, 1); 199 200 mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 1)); 201 202 assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml()).isEqualTo(null); 203 verify(mMockJobManager).queryEntitlementStatusOnceNetworkReady(); 204 } 205 206 @Test onReceive_isSystemUser_jobScheduled()207 public void onReceive_isSystemUser_jobScheduled() { 208 mReceiver.onReceive( 209 mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 0)); 210 211 verify(mMockJobManager).queryEntitlementStatusOnceNetworkReady(); 212 } 213 214 @Test onReceive_notSystemUser_noJobScheduled()215 public void onReceive_notSystemUser_noJobScheduled() { 216 ImsEntitlementReceiver receiver = new ImsEntitlementReceiver(); 217 218 receiver.onReceive( 219 mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 0)); 220 221 verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady(); 222 } 223 224 @Test onReceive_deviceBootUp_jobScheduled()225 public void onReceive_deviceBootUp_jobScheduled() { 226 new EntitlementConfiguration(mContext, LAST_SUB_ID) 227 .update(ENTITLEMENT_VERSION_TWO, RAW_XML_VERSION_0_VALIDITY_0); 228 mIsBootUp = true; 229 230 mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0)); 231 232 verify(mMockJobManager).queryEntitlementStatusOnceNetworkReady(); 233 } 234 235 @Test onReceive_bootCompleteInvalidVers_noJobScheduled()236 public void onReceive_bootCompleteInvalidVers_noJobScheduled() { 237 new EntitlementConfiguration(mContext, LAST_SUB_ID) 238 .update(ENTITLEMENT_VERSION_TWO, RAW_XML_INVALID_VERS); 239 mIsBootUp = true; 240 241 mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0)); 242 243 verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady(); 244 } 245 246 @Test 247 public void onReceiveAndEntitlementUpdatedFromZeroToTwo_bootCompleteInvalidVers_noJobScheduled()248 onReceiveAndEntitlementUpdatedFromZeroToTwo_bootCompleteInvalidVers_noJobScheduled() { 249 new EntitlementConfiguration(mContext, LAST_SUB_ID).update(0, RAW_XML_INVALID_VERS); 250 setEntitlementVersion(ENTITLEMENT_VERSION_TWO); 251 mIsBootUp = true; 252 253 mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0)); 254 255 verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady(); 256 } 257 258 @Test 259 public void onReceiveAndEntitlementUpdatedFromZeroToEight_bootCompleteInvalidVers_JobScheduled()260 onReceiveAndEntitlementUpdatedFromZeroToEight_bootCompleteInvalidVers_JobScheduled() { 261 new EntitlementConfiguration(mContext, LAST_SUB_ID).update(0, RAW_XML_INVALID_VERS); 262 setEntitlementVersion(ENTITLEMENT_VERSION_EIGHT); 263 mIsBootUp = true; 264 265 mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0)); 266 267 verify(mMockJobManager).queryEntitlementStatusOnceNetworkReady(); 268 } 269 270 @Test onReceive_unsupportedEntitlementVersion_noJobScheduled()271 public void onReceive_unsupportedEntitlementVersion_noJobScheduled() { 272 setEntitlementVersion(1); 273 274 mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, 0)); 275 276 verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady(); 277 } 278 279 @Test onReceive_invalidSubId_noJobScheduled()280 public void onReceive_invalidSubId_noJobScheduled() { 281 mReceiver.onReceive(mContext, 282 getCarrierConfigChangedIntent(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 0)); 283 284 verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady(); 285 } 286 287 @Test isBootUp_compareWithLastBootCount_returnResult()288 public void isBootUp_compareWithLastBootCount_returnResult() { 289 int currentBootCount = 290 Settings.Global.getInt( 291 mContext.getContentResolver(), Settings.Global.BOOT_COUNT, /* def= */ -1); 292 setLastBootCount(/* slotId= */ 0, /* count=*/ currentBootCount); 293 setLastBootCount(/* slotId= */ 1, /* count=*/ currentBootCount - 1); 294 ImsEntitlementReceiver receiver = new ImsEntitlementReceiver(); 295 296 assertThat(receiver.isBootUp(mContext, 0)).isFalse(); 297 assertThat(receiver.isBootUp(mContext, 1)).isTrue(); 298 } 299 getCarrierConfigChangedIntent(int subId, int slotId)300 private Intent getCarrierConfigChangedIntent(int subId, int slotId) { 301 Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 302 intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId); 303 intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, slotId); 304 return intent; 305 } 306 setImsProvisioningBool(boolean provisioning)307 private void setImsProvisioningBool(boolean provisioning) { 308 initializeCarrierConfig(); 309 mCarrierConfig.putBoolean( 310 CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL, provisioning); 311 } 312 setEntitlementVersion(int entitlementVersion)313 private void setEntitlementVersion(int entitlementVersion) { 314 initializeCarrierConfig(); 315 mCarrierConfig.putInt(KEY_ENTITLEMENT_VERSION_INT, entitlementVersion); 316 } 317 initializeCarrierConfig()318 private void initializeCarrierConfig() { 319 if (mCarrierConfig == null) { 320 mCarrierConfig = new PersistableBundle(); 321 when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfig); 322 when(mCarrierConfigManager.getConfigForSubId(LAST_SUB_ID)).thenReturn(mCarrierConfig); 323 when(mContext.getSystemService(CarrierConfigManager.class)) 324 .thenReturn(mCarrierConfigManager); 325 } 326 } 327 setLastSubId(int subId, int slotId)328 private void setLastSubId(int subId, int slotId) { 329 SharedPreferences preferences = 330 mContext.getSharedPreferences("PREFERENCE_ACTIVATION_INFO", Context.MODE_PRIVATE); 331 preferences.edit().putInt("last_sub_id_" + slotId, subId).apply(); 332 } 333 setLastBootCount(int slotId, int count)334 private void setLastBootCount(int slotId, int count) { 335 SharedPreferences preferences = 336 mContext.getSharedPreferences("PREFERENCE_ACTIVATION_INFO", Context.MODE_PRIVATE); 337 preferences.edit().putInt("last_boot_count_" + slotId, count).apply(); 338 } 339 useDirectExecutor()340 private void useDirectExecutor() throws Exception { 341 Field field = Executors.class.getDeclaredField("sUseDirectExecutorForTest"); 342 field.setAccessible(true); 343 field.set(null, true); 344 } 345 } 346