1 /* 2 * Copyright (C) 2019 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.server.integrity; 18 19 import static android.content.integrity.AppIntegrityManager.EXTRA_STATUS; 20 import static android.content.integrity.AppIntegrityManager.STATUS_FAILURE; 21 import static android.content.integrity.AppIntegrityManager.STATUS_SUCCESS; 22 import static android.content.integrity.InstallerAllowedByManifestFormula.INSTALLER_CERTIFICATE_NOT_EVALUATED; 23 import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID; 24 import static android.content.pm.PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE; 25 import static android.content.pm.PackageManager.EXTRA_VERIFICATION_INSTALLER_UID; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import static org.junit.Assert.assertEquals; 30 import static org.junit.Assert.assertFalse; 31 import static org.junit.Assert.assertNull; 32 import static org.junit.Assert.assertTrue; 33 import static org.mockito.ArgumentMatchers.any; 34 import static org.mockito.ArgumentMatchers.anyInt; 35 import static org.mockito.ArgumentMatchers.anyLong; 36 import static org.mockito.ArgumentMatchers.eq; 37 import static org.mockito.Mockito.atLeastOnce; 38 import static org.mockito.Mockito.doReturn; 39 import static org.mockito.Mockito.doThrow; 40 import static org.mockito.Mockito.mock; 41 import static org.mockito.Mockito.spy; 42 import static org.mockito.Mockito.verify; 43 import static org.mockito.Mockito.when; 44 45 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; 46 47 import android.content.BroadcastReceiver; 48 import android.content.Context; 49 import android.content.Intent; 50 import android.content.IntentFilter; 51 import android.content.IntentSender; 52 import android.content.integrity.AppInstallMetadata; 53 import android.content.integrity.AtomicFormula; 54 import android.content.integrity.IntegrityFormula; 55 import android.content.integrity.Rule; 56 import android.content.pm.ApplicationInfo; 57 import android.content.pm.PackageInfo; 58 import android.content.pm.PackageManager; 59 import android.content.pm.PackageManagerInternal; 60 import android.content.pm.ParceledListSlice; 61 import android.content.res.Resources; 62 import android.net.Uri; 63 import android.os.Handler; 64 import android.os.Message; 65 import android.provider.Settings; 66 67 import androidx.test.InstrumentationRegistry; 68 69 import com.android.internal.R; 70 import com.android.server.compat.PlatformCompat; 71 import com.android.server.integrity.engine.RuleEvaluationEngine; 72 import com.android.server.integrity.model.IntegrityCheckResult; 73 import com.android.server.pm.parsing.PackageParser2; 74 import com.android.server.pm.parsing.TestPackageParser2; 75 import com.android.server.testutils.TestUtils; 76 77 import org.junit.After; 78 import org.junit.Before; 79 import org.junit.Test; 80 import org.junit.runner.RunWith; 81 import org.junit.runners.JUnit4; 82 import org.mockito.ArgumentCaptor; 83 import org.mockito.Mock; 84 import org.mockito.junit.MockitoJUnit; 85 import org.mockito.junit.MockitoRule; 86 87 import java.io.File; 88 import java.io.IOException; 89 import java.io.InputStream; 90 import java.nio.file.Files; 91 import java.util.Arrays; 92 import java.util.List; 93 import java.util.Map; 94 import java.util.function.Supplier; 95 96 /** Unit test for {@link com.android.server.integrity.AppIntegrityManagerServiceImpl} */ 97 @RunWith(JUnit4.class) 98 public class AppIntegrityManagerServiceImplTest { 99 private static final String TEST_APP_PATH = 100 "AppIntegrityManagerServiceImplTest/AppIntegrityManagerServiceTestApp.apk"; 101 102 private static final String TEST_APP_TWO_CERT_PATH = 103 "AppIntegrityManagerServiceImplTest/DummyAppTwoCerts.apk"; 104 105 private static final String TEST_APP_SOURCE_STAMP_PATH = 106 "AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk"; 107 108 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; 109 private static final String VERSION = "version"; 110 private static final String TEST_FRAMEWORK_PACKAGE = "com.android.frameworks.servicestests"; 111 112 private static final String PACKAGE_NAME = "com.test.app"; 113 114 private static final long VERSION_CODE = 100; 115 private static final String INSTALLER = "com.long.random.test.installer.name"; 116 117 // These are obtained by running the test and checking logcat. 118 private static final String APP_CERT = 119 "F14CFECF5070874C05D3D2FA98E046BE20BDE02A0DC74BAF6B59C6A0E4C06850"; 120 // We use SHA256 for package names longer than 32 characters. 121 private static final String INSTALLER_SHA256 = 122 "30F41A7CBF96EE736A54DD6DF759B50ED3CC126ABCEF694E167C324F5976C227"; 123 private static final String SOURCE_STAMP_CERTIFICATE_HASH = 124 "C6E737809CEF2B08CC6694892215F82A5E8FBC3C2A0F6212770310B90622D2D9"; 125 126 private static final String DUMMY_APP_TWO_CERTS_CERT_1 = 127 "C0369C2A1096632429DFA8433068AECEAD00BAC337CA92A175036D39CC9AFE94"; 128 private static final String DUMMY_APP_TWO_CERTS_CERT_2 = 129 "94366E0A80F3A3F0D8171A15760B88E228CD6E1101F0414C98878724FBE70147"; 130 131 private static final String PLAY_STORE_PKG = "com.android.vending"; 132 private static final String ADB_INSTALLER = "adb"; 133 private static final String PLAY_STORE_CERT = "play_store_cert"; 134 135 @org.junit.Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); 136 137 @Mock PackageManagerInternal mPackageManagerInternal; 138 @Mock PlatformCompat mPlatformCompat; 139 @Mock Context mMockContext; 140 @Mock Resources mMockResources; 141 @Mock RuleEvaluationEngine mRuleEvaluationEngine; 142 @Mock IntegrityFileManager mIntegrityFileManager; 143 @Mock Handler mHandler; 144 145 private Supplier<PackageParser2> mParserSupplier = TestPackageParser2::new; 146 147 private final Context mRealContext = InstrumentationRegistry.getTargetContext(); 148 149 private PackageManager mSpyPackageManager; 150 private File mTestApk; 151 private File mTestApkTwoCerts; 152 private File mTestApkSourceStamp; 153 154 // under test 155 private AppIntegrityManagerServiceImpl mService; 156 157 @Before setup()158 public void setup() throws Exception { 159 mTestApk = File.createTempFile("AppIntegrity", ".apk"); 160 try (InputStream inputStream = mRealContext.getAssets().open(TEST_APP_PATH)) { 161 Files.copy(inputStream, mTestApk.toPath(), REPLACE_EXISTING); 162 } 163 164 mTestApkTwoCerts = File.createTempFile("AppIntegrityTwoCerts", ".apk"); 165 try (InputStream inputStream = mRealContext.getAssets().open(TEST_APP_TWO_CERT_PATH)) { 166 Files.copy(inputStream, mTestApkTwoCerts.toPath(), REPLACE_EXISTING); 167 } 168 169 mTestApkSourceStamp = File.createTempFile("AppIntegritySourceStamp", ".apk"); 170 try (InputStream inputStream = mRealContext.getAssets().open(TEST_APP_SOURCE_STAMP_PATH)) { 171 Files.copy(inputStream, mTestApkSourceStamp.toPath(), REPLACE_EXISTING); 172 } 173 174 mService = 175 new AppIntegrityManagerServiceImpl( 176 mMockContext, 177 mPackageManagerInternal, 178 mParserSupplier, 179 mRuleEvaluationEngine, 180 mIntegrityFileManager, 181 mHandler); 182 183 mSpyPackageManager = spy(mRealContext.getPackageManager()); 184 // setup mocks to prevent NPE 185 when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager); 186 when(mMockContext.getResources()).thenReturn(mMockResources); 187 when(mMockResources.getStringArray(anyInt())).thenReturn(new String[] {}); 188 when(mIntegrityFileManager.initialized()).thenReturn(true); 189 // These are needed to override the Settings.Global.get result. 190 when(mMockContext.getContentResolver()).thenReturn(mRealContext.getContentResolver()); 191 setIntegrityCheckIncludesRuleProvider(true); 192 } 193 194 @After tearDown()195 public void tearDown() throws Exception { 196 mTestApk.delete(); 197 mTestApkTwoCerts.delete(); 198 mTestApkSourceStamp.delete(); 199 } 200 201 @Test updateRuleSet_notAuthorized()202 public void updateRuleSet_notAuthorized() throws Exception { 203 makeUsSystemApp(); 204 Rule rule = 205 new Rule( 206 new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true), 207 Rule.DENY); 208 TestUtils.assertExpectException( 209 SecurityException.class, 210 "Only system packages specified in config_integrityRuleProviderPackages are" 211 + " allowed to call this method.", 212 () -> 213 mService.updateRuleSet( 214 VERSION, 215 new ParceledListSlice<>(Arrays.asList(rule)), 216 /* statusReceiver= */ null)); 217 } 218 219 @Test updateRuleSet_notSystemApp()220 public void updateRuleSet_notSystemApp() throws Exception { 221 whitelistUsAsRuleProvider(); 222 makeUsSystemApp(false); 223 Rule rule = 224 new Rule( 225 new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true), 226 Rule.DENY); 227 TestUtils.assertExpectException( 228 SecurityException.class, 229 "Only system packages specified in config_integrityRuleProviderPackages are" 230 + " allowed to call this method.", 231 () -> 232 mService.updateRuleSet( 233 VERSION, 234 new ParceledListSlice<>(Arrays.asList(rule)), 235 /* statusReceiver= */ null)); 236 } 237 238 @Test updateRuleSet_authorized()239 public void updateRuleSet_authorized() throws Exception { 240 whitelistUsAsRuleProvider(); 241 makeUsSystemApp(); 242 Rule rule = 243 new Rule( 244 new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true), 245 Rule.DENY); 246 247 // no SecurityException 248 mService.updateRuleSet( 249 VERSION, new ParceledListSlice<>(Arrays.asList(rule)), mock(IntentSender.class)); 250 } 251 252 @Test updateRuleSet_correctMethodCall()253 public void updateRuleSet_correctMethodCall() throws Exception { 254 whitelistUsAsRuleProvider(); 255 makeUsSystemApp(); 256 IntentSender mockReceiver = mock(IntentSender.class); 257 List<Rule> rules = 258 Arrays.asList( 259 new Rule( 260 IntegrityFormula.Application.packageNameEquals(PACKAGE_NAME), 261 Rule.DENY)); 262 263 mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver); 264 runJobInHandler(); 265 266 verify(mIntegrityFileManager).writeRules(VERSION, TEST_FRAMEWORK_PACKAGE, rules); 267 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 268 verify(mockReceiver).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any()); 269 assertEquals(STATUS_SUCCESS, intentCaptor.getValue().getIntExtra(EXTRA_STATUS, -1)); 270 } 271 272 @Test updateRuleSet_fail()273 public void updateRuleSet_fail() throws Exception { 274 whitelistUsAsRuleProvider(); 275 makeUsSystemApp(); 276 doThrow(new IOException()).when(mIntegrityFileManager).writeRules(any(), any(), any()); 277 IntentSender mockReceiver = mock(IntentSender.class); 278 List<Rule> rules = 279 Arrays.asList( 280 new Rule( 281 IntegrityFormula.Application.packageNameEquals(PACKAGE_NAME), 282 Rule.DENY)); 283 284 mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver); 285 runJobInHandler(); 286 287 verify(mIntegrityFileManager).writeRules(VERSION, TEST_FRAMEWORK_PACKAGE, rules); 288 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 289 verify(mockReceiver).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any()); 290 assertEquals(STATUS_FAILURE, intentCaptor.getValue().getIntExtra(EXTRA_STATUS, -1)); 291 } 292 293 @Test broadcastReceiverRegistration()294 public void broadcastReceiverRegistration() throws Exception { 295 whitelistUsAsRuleProvider(); 296 makeUsSystemApp(); 297 ArgumentCaptor<IntentFilter> intentFilterCaptor = 298 ArgumentCaptor.forClass(IntentFilter.class); 299 300 verify(mMockContext).registerReceiver(any(), intentFilterCaptor.capture(), any(), any()); 301 assertEquals(1, intentFilterCaptor.getValue().countActions()); 302 assertEquals( 303 Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION, 304 intentFilterCaptor.getValue().getAction(0)); 305 assertEquals(1, intentFilterCaptor.getValue().countDataTypes()); 306 assertEquals(PACKAGE_MIME_TYPE, intentFilterCaptor.getValue().getDataType(0)); 307 } 308 309 @Test handleBroadcast_correctArgs()310 public void handleBroadcast_correctArgs() throws Exception { 311 whitelistUsAsRuleProvider(); 312 makeUsSystemApp(); 313 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 314 ArgumentCaptor.forClass(BroadcastReceiver.class); 315 verify(mMockContext) 316 .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); 317 Intent intent = makeVerificationIntent(); 318 when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow()); 319 320 broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent); 321 runJobInHandler(); 322 323 ArgumentCaptor<AppInstallMetadata> metadataCaptor = 324 ArgumentCaptor.forClass(AppInstallMetadata.class); 325 verify(mRuleEvaluationEngine).evaluate(metadataCaptor.capture()); 326 AppInstallMetadata appInstallMetadata = metadataCaptor.getValue(); 327 assertEquals(PACKAGE_NAME, appInstallMetadata.getPackageName()); 328 assertThat(appInstallMetadata.getAppCertificates()).containsExactly(APP_CERT); 329 assertEquals(INSTALLER_SHA256, appInstallMetadata.getInstallerName()); 330 // we cannot check installer cert because it seems to be device specific. 331 assertEquals(VERSION_CODE, appInstallMetadata.getVersionCode()); 332 assertFalse(appInstallMetadata.isPreInstalled()); 333 // Asserting source stamp not present. 334 assertFalse(appInstallMetadata.isStampPresent()); 335 assertFalse(appInstallMetadata.isStampVerified()); 336 assertFalse(appInstallMetadata.isStampTrusted()); 337 assertNull(appInstallMetadata.getStampCertificateHash()); 338 // These are hardcoded in the test apk android manifest 339 Map<String, String> allowedInstallers = 340 appInstallMetadata.getAllowedInstallersAndCertificates(); 341 assertEquals(2, allowedInstallers.size()); 342 assertEquals(PLAY_STORE_CERT, allowedInstallers.get(PLAY_STORE_PKG)); 343 assertEquals(INSTALLER_CERTIFICATE_NOT_EVALUATED, allowedInstallers.get(ADB_INSTALLER)); 344 } 345 346 @Test handleBroadcast_correctArgs_multipleCerts()347 public void handleBroadcast_correctArgs_multipleCerts() throws Exception { 348 whitelistUsAsRuleProvider(); 349 makeUsSystemApp(); 350 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 351 ArgumentCaptor.forClass(BroadcastReceiver.class); 352 verify(mMockContext) 353 .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); 354 Intent intent = makeVerificationIntent(); 355 intent.setDataAndType(Uri.fromFile(mTestApkTwoCerts), PACKAGE_MIME_TYPE); 356 when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow()); 357 358 broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent); 359 runJobInHandler(); 360 361 ArgumentCaptor<AppInstallMetadata> metadataCaptor = 362 ArgumentCaptor.forClass(AppInstallMetadata.class); 363 verify(mRuleEvaluationEngine).evaluate(metadataCaptor.capture()); 364 AppInstallMetadata appInstallMetadata = metadataCaptor.getValue(); 365 assertThat(appInstallMetadata.getAppCertificates()) 366 .containsExactly(DUMMY_APP_TWO_CERTS_CERT_1, DUMMY_APP_TWO_CERTS_CERT_2); 367 } 368 369 @Test handleBroadcast_correctArgs_sourceStamp()370 public void handleBroadcast_correctArgs_sourceStamp() throws Exception { 371 whitelistUsAsRuleProvider(); 372 makeUsSystemApp(); 373 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 374 ArgumentCaptor.forClass(BroadcastReceiver.class); 375 verify(mMockContext) 376 .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); 377 Intent intent = makeVerificationIntent(); 378 intent.setDataAndType(Uri.fromFile(mTestApkSourceStamp), PACKAGE_MIME_TYPE); 379 when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow()); 380 381 broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent); 382 runJobInHandler(); 383 384 ArgumentCaptor<AppInstallMetadata> metadataCaptor = 385 ArgumentCaptor.forClass(AppInstallMetadata.class); 386 verify(mRuleEvaluationEngine).evaluate(metadataCaptor.capture()); 387 AppInstallMetadata appInstallMetadata = metadataCaptor.getValue(); 388 assertTrue(appInstallMetadata.isStampPresent()); 389 assertTrue(appInstallMetadata.isStampVerified()); 390 assertTrue(appInstallMetadata.isStampTrusted()); 391 assertEquals(SOURCE_STAMP_CERTIFICATE_HASH, appInstallMetadata.getStampCertificateHash()); 392 } 393 394 @Test handleBroadcast_allow()395 public void handleBroadcast_allow() throws Exception { 396 whitelistUsAsRuleProvider(); 397 makeUsSystemApp(); 398 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 399 ArgumentCaptor.forClass(BroadcastReceiver.class); 400 verify(mMockContext) 401 .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); 402 Intent intent = makeVerificationIntent(); 403 when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow()); 404 405 broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent); 406 runJobInHandler(); 407 408 verify(mPackageManagerInternal) 409 .setIntegrityVerificationResult( 410 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW); 411 } 412 413 @Test handleBroadcast_reject()414 public void handleBroadcast_reject() throws Exception { 415 whitelistUsAsRuleProvider(); 416 makeUsSystemApp(); 417 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 418 ArgumentCaptor.forClass(BroadcastReceiver.class); 419 verify(mMockContext) 420 .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); 421 when(mRuleEvaluationEngine.evaluate(any())) 422 .thenReturn( 423 IntegrityCheckResult.deny( 424 Arrays.asList( 425 new Rule( 426 new AtomicFormula.BooleanAtomicFormula( 427 AtomicFormula.PRE_INSTALLED, false), 428 Rule.DENY)))); 429 Intent intent = makeVerificationIntent(); 430 431 broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent); 432 runJobInHandler(); 433 434 verify(mPackageManagerInternal) 435 .setIntegrityVerificationResult( 436 1, PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT); 437 } 438 439 @Test handleBroadcast_notInitialized()440 public void handleBroadcast_notInitialized() throws Exception { 441 whitelistUsAsRuleProvider(); 442 makeUsSystemApp(); 443 when(mIntegrityFileManager.initialized()).thenReturn(false); 444 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 445 ArgumentCaptor.forClass(BroadcastReceiver.class); 446 verify(mMockContext) 447 .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); 448 Intent intent = makeVerificationIntent(); 449 when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow()); 450 451 broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent); 452 runJobInHandler(); 453 454 // The evaluation will still run since we still evaluate manifest based rules. 455 verify(mPackageManagerInternal) 456 .setIntegrityVerificationResult( 457 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW); 458 } 459 460 @Test verifierAsInstaller_skipIntegrityVerification()461 public void verifierAsInstaller_skipIntegrityVerification() throws Exception { 462 whitelistUsAsRuleProvider(); 463 makeUsSystemApp(); 464 setIntegrityCheckIncludesRuleProvider(false); 465 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 466 ArgumentCaptor.forClass(BroadcastReceiver.class); 467 verify(mMockContext, atLeastOnce()) 468 .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); 469 Intent intent = makeVerificationIntent(TEST_FRAMEWORK_PACKAGE); 470 when(mRuleEvaluationEngine.evaluate(any())) 471 .thenReturn(IntegrityCheckResult.deny(/* rule= */ null)); 472 473 broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent); 474 runJobInHandler(); 475 476 verify(mPackageManagerInternal) 477 .setIntegrityVerificationResult( 478 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW); 479 } 480 481 @Test getCurrentRules()482 public void getCurrentRules() throws Exception { 483 whitelistUsAsRuleProvider(); 484 makeUsSystemApp(); 485 Rule rule = new Rule(IntegrityFormula.Application.packageNameEquals("package"), Rule.DENY); 486 when(mIntegrityFileManager.readRules(any())).thenReturn(Arrays.asList(rule)); 487 488 assertThat(mService.getCurrentRules().getList()).containsExactly(rule); 489 } 490 491 @Test getWhitelistedRuleProviders_returnsEmptyForNonSystemApps()492 public void getWhitelistedRuleProviders_returnsEmptyForNonSystemApps() throws Exception { 493 whitelistUsAsRuleProvider(); 494 makeUsSystemApp(false); 495 496 assertThat(mService.getWhitelistedRuleProviders()).isEmpty(); 497 } 498 499 @Test getWhitelistedRuleProviders()500 public void getWhitelistedRuleProviders() throws Exception { 501 whitelistUsAsRuleProvider(); 502 makeUsSystemApp(); 503 504 assertThat(mService.getWhitelistedRuleProviders()).containsExactly(TEST_FRAMEWORK_PACKAGE); 505 } 506 whitelistUsAsRuleProvider()507 private void whitelistUsAsRuleProvider() { 508 Resources mockResources = mock(Resources.class); 509 when(mockResources.getStringArray(R.array.config_integrityRuleProviderPackages)) 510 .thenReturn(new String[] {TEST_FRAMEWORK_PACKAGE}); 511 when(mMockContext.getResources()).thenReturn(mockResources); 512 } 513 runJobInHandler()514 private void runJobInHandler() { 515 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 516 // sendMessageAtTime is the first non-final method in the call chain when "post" is invoked. 517 verify(mHandler).sendMessageAtTime(messageCaptor.capture(), anyLong()); 518 messageCaptor.getValue().getCallback().run(); 519 } 520 makeUsSystemApp()521 private void makeUsSystemApp() throws Exception { 522 makeUsSystemApp(true); 523 } 524 makeUsSystemApp(boolean isSystemApp)525 private void makeUsSystemApp(boolean isSystemApp) throws Exception { 526 PackageInfo packageInfo = 527 mRealContext.getPackageManager().getPackageInfo(TEST_FRAMEWORK_PACKAGE, 0); 528 if (isSystemApp) { 529 packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 530 } else { 531 packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; 532 } 533 doReturn(packageInfo) 534 .when(mSpyPackageManager) 535 .getPackageInfo(eq(TEST_FRAMEWORK_PACKAGE), anyInt()); 536 when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager); 537 } 538 makeVerificationIntent()539 private Intent makeVerificationIntent() throws Exception { 540 PackageInfo packageInfo = 541 mRealContext 542 .getPackageManager() 543 .getPackageInfo( 544 TEST_FRAMEWORK_PACKAGE, PackageManager.GET_SIGNING_CERTIFICATES); 545 doReturn(packageInfo).when(mSpyPackageManager).getPackageInfo(eq(INSTALLER), anyInt()); 546 doReturn(1).when(mSpyPackageManager).getPackageUid(eq(INSTALLER), anyInt()); 547 doReturn(new String[]{INSTALLER}).when(mSpyPackageManager).getPackagesForUid(anyInt()); 548 return makeVerificationIntent(INSTALLER); 549 } 550 makeVerificationIntent(String installer)551 private Intent makeVerificationIntent(String installer) throws Exception { 552 Intent intent = new Intent(); 553 intent.setDataAndType(Uri.fromFile(mTestApk), PACKAGE_MIME_TYPE); 554 intent.setAction(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION); 555 intent.putExtra(EXTRA_VERIFICATION_ID, 1); 556 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, PACKAGE_NAME); 557 intent.putExtra(EXTRA_VERIFICATION_INSTALLER_PACKAGE, installer); 558 intent.putExtra( 559 EXTRA_VERIFICATION_INSTALLER_UID, 560 mMockContext.getPackageManager().getPackageUid(installer, /* flags= */ 0)); 561 intent.putExtra(Intent.EXTRA_LONG_VERSION_CODE, VERSION_CODE); 562 return intent; 563 } 564 setIntegrityCheckIncludesRuleProvider(boolean shouldInclude)565 private void setIntegrityCheckIncludesRuleProvider(boolean shouldInclude) throws Exception { 566 int value = shouldInclude ? 1 : 0; 567 Settings.Global.putInt( 568 mRealContext.getContentResolver(), 569 Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER, 570 value); 571 assertThat( 572 Settings.Global.getInt( 573 mRealContext.getContentResolver(), 574 Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER, 575 -1) 576 == 1) 577 .isEqualTo(shouldInclude); 578 } 579 } 580