1 /* 2 * Copyright (C) 2014 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.cts.isolatedsplitapp; 18 19 import static org.hamcrest.CoreMatchers.*; 20 import static org.junit.Assert.*; 21 22 import android.app.Activity; 23 import android.app.Instrumentation; 24 import android.content.BroadcastReceiver; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.res.Configuration; 29 import android.content.res.Resources; 30 import android.graphics.drawable.ColorDrawable; 31 import android.graphics.drawable.Drawable; 32 import android.os.Bundle; 33 import android.view.View; 34 import android.widget.LinearLayout; 35 36 import androidx.test.InstrumentationRegistry; 37 import androidx.test.rule.ActivityTestRule; 38 import androidx.test.runner.AndroidJUnit4; 39 40 import org.junit.Before; 41 import org.junit.Rule; 42 import org.junit.Test; 43 import org.junit.rules.TestRule; 44 import org.junit.runner.Description; 45 import org.junit.runner.RunWith; 46 import org.junit.runners.model.Statement; 47 48 import java.util.Locale; 49 import java.util.concurrent.CompletableFuture; 50 import java.util.concurrent.TimeUnit; 51 52 @RunWith(AndroidJUnit4.class) 53 public class SplitAppTest { 54 private static final String PACKAGE = "com.android.cts.isolatedsplitapp"; 55 56 private static final ComponentName BASE_ACTIVITY = 57 ComponentName.createRelative(PACKAGE, ".BaseActivity"); 58 private static final ComponentName FEATURE_A_ACTIVITY = 59 ComponentName.createRelative(PACKAGE, ".feature_a.FeatureAActivity"); 60 private static final ComponentName FEATURE_B_ACTIVITY = 61 ComponentName.createRelative(PACKAGE, ".feature_b.FeatureBActivity"); 62 private static final ComponentName FEATURE_C_ACTIVITY = 63 ComponentName.createRelative(PACKAGE, ".feature_c.FeatureCActivity"); 64 65 private static final String FEATURE_A_STRING = 66 "com.android.cts.isolatedsplitapp.feature_a:string/feature_a_string"; 67 private static final String FEATURE_B_STRING = 68 "com.android.cts.isolatedsplitapp.feature_b:string/feature_b_string"; 69 private static final String FEATURE_C_STRING = 70 "com.android.cts.isolatedsplitapp.feature_c:string/feature_c_string"; 71 private static final String FEATURE_A_TEXTVIEW_ID = 72 "com.android.cts.isolatedsplitapp.feature_a:id/feature_a_text"; 73 private static final String FEATURE_B_TEXTVIEW_ID = 74 "com.android.cts.isolatedsplitapp.feature_b:id/feature_b_text"; 75 private static final String FEATURE_C_TEXTVIEW_ID = 76 "com.android.cts.isolatedsplitapp.feature_c:id/feature_c_text"; 77 78 private static final Configuration PL = new Configuration(); 79 static { 80 PL.setLocale(Locale.forLanguageTag("pl")); 81 } 82 83 // Do not launch this activity lazily. We use this rule to launch all Activities, 84 // so we use #launchActivity() with the correct Intent. 85 @Rule 86 public ActivityTestRule<Activity> mActivityRule = 87 new ActivityTestRule<>(Activity.class, true /*initialTouchMode*/, 88 false /*launchActivity*/); 89 90 @Rule 91 public AppContextTestRule mAppContextTestRule = new AppContextTestRule(); 92 93 @Before setUp()94 public void setUp() { 95 BaseActivity.setOverrideConfiguration(null); 96 } 97 98 @Test shouldLoadDefault()99 public void shouldLoadDefault() throws Exception { 100 final Activity activity = mActivityRule.launchActivity( 101 new Intent().setComponent(BASE_ACTIVITY)); 102 final TestTheme testTheme = new TestTheme(activity, R.style.Theme_Base); 103 final Resources resources = activity.getResources(); 104 assertThat(resources, notNullValue()); 105 106 assertThat(resources.getString(R.string.base_string), equalTo("Base String Default")); 107 testTheme.assertThemeBaseValues(); 108 109 // Test the theme applied to the activity correctly 110 assertActivityThemeApplied(activity, testTheme); 111 112 // The base does not depend on any splits so no splits should be accessible. 113 assertActivitiesDoNotExist(activity, FEATURE_A_ACTIVITY, FEATURE_B_ACTIVITY, 114 FEATURE_C_ACTIVITY); 115 assertResourcesDoNotExist(activity, FEATURE_A_STRING, FEATURE_B_STRING, FEATURE_C_STRING, 116 TestTheme.THEME_FEATURE_A, TestTheme.THEME_FEATURE_B, TestTheme.THEME_FEATURE_C); 117 } 118 119 @Test shouldLoadPolishLocale()120 public void shouldLoadPolishLocale() throws Exception { 121 BaseActivity.setOverrideConfiguration(PL); 122 final Activity activity = mActivityRule.launchActivity( 123 new Intent().setComponent(BASE_ACTIVITY)); 124 final TestTheme testTheme = new TestTheme(activity, R.style.Theme_Base); 125 final Resources resources = activity.getResources(); 126 assertThat(resources, notNullValue()); 127 128 assertThat(resources.getString(R.string.base_string), equalTo("Base String Polish")); 129 testTheme.assertThemeBaseValues_pl(); 130 131 // Test the theme applied to the activity correctly 132 assertActivityThemeApplied(activity, testTheme); 133 134 // The base does not depend on any splits so no splits should be accessible. 135 assertActivitiesDoNotExist(activity, FEATURE_A_ACTIVITY, FEATURE_B_ACTIVITY, 136 FEATURE_C_ACTIVITY); 137 assertResourcesDoNotExist(activity, FEATURE_A_STRING, FEATURE_B_STRING, FEATURE_C_STRING, 138 TestTheme.THEME_FEATURE_A, TestTheme.THEME_FEATURE_B, TestTheme.THEME_FEATURE_C); 139 } 140 141 @Test shouldLoadFeatureADefault()142 public void shouldLoadFeatureADefault() throws Exception { 143 final Activity activity = mActivityRule.launchActivity( 144 new Intent().setComponent(FEATURE_A_ACTIVITY)); 145 final TestTheme testTheme = new TestTheme(activity, TestTheme.THEME_FEATURE_A); 146 final Resources resources = activity.getResources(); 147 assertThat(resources, notNullValue()); 148 149 assertThat(resources.getString(R.string.base_string), equalTo("Base String Default")); 150 new TestTheme(activity, R.style.Theme_Base).assertThemeBaseValues(); 151 152 int resourceId = resources.getIdentifier(FEATURE_A_STRING, null, null); 153 assertThat(resources.getString(resourceId), equalTo("Feature A String Default")); 154 testTheme.assertThemeFeatureAValues(); 155 156 // Test the theme applied to the activity correctly 157 assertActivityThemeApplied(activity, testTheme); 158 assertTextViewBGColor(activity, FEATURE_A_TEXTVIEW_ID, testTheme.mColorBackground); 159 160 assertActivitiesDoNotExist(activity, FEATURE_B_ACTIVITY, FEATURE_C_ACTIVITY); 161 assertResourcesDoNotExist(activity, FEATURE_B_STRING, FEATURE_C_STRING, 162 TestTheme.THEME_FEATURE_B, TestTheme.THEME_FEATURE_C); 163 } 164 165 @Test shouldLoadFeatureAPolishLocale()166 public void shouldLoadFeatureAPolishLocale() throws Exception { 167 BaseActivity.setOverrideConfiguration(PL); 168 final Activity activity = mActivityRule.launchActivity( 169 new Intent().setComponent(FEATURE_A_ACTIVITY)); 170 final TestTheme testTheme = new TestTheme(activity, TestTheme.THEME_FEATURE_A); 171 final Resources resources = activity.getResources(); 172 assertThat(resources, notNullValue()); 173 174 assertThat(resources.getString(R.string.base_string), equalTo("Base String Polish")); 175 new TestTheme(activity, R.style.Theme_Base).assertThemeBaseValues_pl(); 176 177 int resourceId = resources.getIdentifier(FEATURE_A_STRING, null, null); 178 assertThat(resources.getString(resourceId), equalTo("Feature A String Polish")); 179 testTheme.assertThemeFeatureAValues_pl(); 180 181 // Test the theme applied to the activity correctly 182 assertActivityThemeApplied(activity, testTheme); 183 assertTextViewBGColor(activity, FEATURE_A_TEXTVIEW_ID, testTheme.mColorBackground); 184 185 assertActivitiesDoNotExist(activity, FEATURE_B_ACTIVITY, FEATURE_C_ACTIVITY); 186 assertResourcesDoNotExist(activity, FEATURE_B_STRING, FEATURE_C_STRING, 187 TestTheme.THEME_FEATURE_B, TestTheme.THEME_FEATURE_C); 188 } 189 190 @Test shouldLoadFeatureAReceivers()191 public void shouldLoadFeatureAReceivers() throws Exception { 192 final Context context = mAppContextTestRule.getContext(); 193 final ExtrasResultReceiver receiver = sendOrderedBroadcast(context); 194 final Bundle results = receiver.get(); 195 assertThat(results.getString("base"), equalTo("Base String Default")); 196 assertThat(results.getString("feature_a"), equalTo("Feature A String Default")); 197 assertThat(results.getString("feature_b"), nullValue()); 198 assertThat(results.getString("feature_c"), nullValue()); 199 } 200 201 @Test shouldLoadFeatureBDefault()202 public void shouldLoadFeatureBDefault() throws Exception { 203 // Feature B depends on A, so we expect both to be available. 204 final Activity activity = mActivityRule.launchActivity( 205 new Intent().setComponent(FEATURE_B_ACTIVITY)); 206 final TestTheme testTheme = new TestTheme(activity, TestTheme.THEME_FEATURE_B); 207 final Resources resources = activity.getResources(); 208 assertThat(resources, notNullValue()); 209 210 assertThat(resources.getString(R.string.base_string), equalTo("Base String Default")); 211 new TestTheme(activity, R.style.Theme_Base).assertThemeBaseValues(); 212 213 int resourceId = resources.getIdentifier(FEATURE_A_STRING, null, null); 214 assertThat(resources.getString(resourceId), equalTo("Feature A String Default")); 215 new TestTheme(activity, TestTheme.THEME_FEATURE_A).assertThemeFeatureAValues(); 216 217 resourceId = resources.getIdentifier(FEATURE_B_STRING, null, null); 218 assertThat(resources.getString(resourceId), equalTo("Feature B String Default")); 219 testTheme.assertThemeFeatureBValues(); 220 221 // Test the theme applied to the activity correctly 222 assertActivityThemeApplied(activity, testTheme); 223 assertTextViewBGColor(activity, FEATURE_B_TEXTVIEW_ID, testTheme.mColorBackground); 224 225 assertActivitiesDoNotExist(activity, FEATURE_C_ACTIVITY); 226 assertResourcesDoNotExist(activity, FEATURE_C_STRING, TestTheme.THEME_FEATURE_C); 227 } 228 229 @Test shouldLoadFeatureBPolishLocale()230 public void shouldLoadFeatureBPolishLocale() throws Exception { 231 BaseActivity.setOverrideConfiguration(PL); 232 final Activity activity = mActivityRule.launchActivity( 233 new Intent().setComponent(FEATURE_B_ACTIVITY)); 234 final TestTheme testTheme = new TestTheme(activity, TestTheme.THEME_FEATURE_B); 235 final Resources resources = activity.getResources(); 236 assertThat(resources, notNullValue()); 237 238 assertThat(resources.getString(R.string.base_string), equalTo("Base String Polish")); 239 new TestTheme(activity, R.style.Theme_Base).assertThemeBaseValues_pl(); 240 241 int resourceId = resources.getIdentifier(FEATURE_A_STRING, null, null); 242 assertThat(resources.getString(resourceId), equalTo("Feature A String Polish")); 243 new TestTheme(activity, TestTheme.THEME_FEATURE_A).assertThemeFeatureAValues_pl(); 244 245 resourceId = resources.getIdentifier(FEATURE_B_STRING, null, null); 246 assertThat(resources.getString(resourceId), equalTo("Feature B String Polish")); 247 testTheme.assertThemeFeatureBValues_pl(); 248 249 // Test the theme applied to the activity correctly 250 assertActivityThemeApplied(activity, testTheme); 251 assertTextViewBGColor(activity, FEATURE_B_TEXTVIEW_ID, testTheme.mColorBackground); 252 253 assertActivitiesDoNotExist(activity, FEATURE_C_ACTIVITY); 254 assertResourcesDoNotExist(activity, FEATURE_C_STRING, TestTheme.THEME_FEATURE_C); 255 } 256 257 @Test shouldLoadFeatureAAndBReceivers()258 public void shouldLoadFeatureAAndBReceivers() throws Exception { 259 final Context context = mAppContextTestRule.getContext(); 260 final ExtrasResultReceiver receiver = sendOrderedBroadcast(context); 261 final Bundle results = receiver.get(); 262 assertThat(results.getString("base"), equalTo("Base String Default")); 263 assertThat(results.getString("feature_a"), equalTo("Feature A String Default")); 264 assertThat(results.getString("feature_b"), equalTo("Feature B String Default")); 265 assertThat(results.getString("feature_c"), nullValue()); 266 } 267 268 @Test shouldLoadFeatureCDefault()269 public void shouldLoadFeatureCDefault() throws Exception { 270 final Activity activity = mActivityRule.launchActivity( 271 new Intent().setComponent(FEATURE_C_ACTIVITY)); 272 final TestTheme testTheme = new TestTheme(activity, TestTheme.THEME_FEATURE_C); 273 final Resources resources = activity.getResources(); 274 assertThat(resources, notNullValue()); 275 276 assertThat(resources.getString(R.string.base_string), equalTo("Base String Default")); 277 new TestTheme(activity, R.style.Theme_Base).assertThemeBaseValues(); 278 279 int resourceId = resources.getIdentifier(FEATURE_C_STRING, null, null); 280 assertThat(resources.getString(resourceId), equalTo("Feature C String Default")); 281 testTheme.assertThemeFeatureCValues(); 282 283 // Test the theme applied to the activity correctly 284 assertActivityThemeApplied(activity, testTheme); 285 assertTextViewBGColor(activity, FEATURE_C_TEXTVIEW_ID, testTheme.mColorBackground); 286 287 assertActivitiesDoNotExist(activity, FEATURE_A_ACTIVITY, FEATURE_B_ACTIVITY); 288 assertResourcesDoNotExist(activity, FEATURE_A_STRING, FEATURE_B_STRING, 289 TestTheme.THEME_FEATURE_A, TestTheme.THEME_FEATURE_B); 290 } 291 292 @Test shouldLoadFeatureCPolishLocale()293 public void shouldLoadFeatureCPolishLocale() throws Exception { 294 BaseActivity.setOverrideConfiguration(PL); 295 final Activity activity = mActivityRule.launchActivity( 296 new Intent().setComponent(FEATURE_C_ACTIVITY)); 297 final TestTheme testTheme = new TestTheme(activity, TestTheme.THEME_FEATURE_C); 298 final Resources resources = activity.getResources(); 299 assertThat(resources, notNullValue()); 300 301 assertThat(resources.getString(R.string.base_string), equalTo("Base String Polish")); 302 new TestTheme(activity, R.style.Theme_Base).assertThemeBaseValues_pl(); 303 304 int resourceId = resources.getIdentifier(FEATURE_C_STRING, null, null); 305 assertThat(resources.getString(resourceId), equalTo("Feature C String Polish")); 306 testTheme.assertThemeFeatureCValues_pl(); 307 308 // Test the theme applied to the activity correctly 309 assertActivityThemeApplied(activity, testTheme); 310 assertTextViewBGColor(activity, FEATURE_C_TEXTVIEW_ID, testTheme.mColorBackground); 311 312 assertActivitiesDoNotExist(activity, FEATURE_A_ACTIVITY, FEATURE_B_ACTIVITY); 313 assertResourcesDoNotExist(activity, FEATURE_A_STRING, FEATURE_B_STRING, 314 TestTheme.THEME_FEATURE_A, TestTheme.THEME_FEATURE_B); 315 } 316 317 @Test shouldLoadFeatureADiffRevision()318 public void shouldLoadFeatureADiffRevision() throws Exception { 319 final Activity activity = mActivityRule.launchActivity( 320 new Intent().setComponent(FEATURE_A_ACTIVITY)); 321 final TestTheme testTheme = new TestTheme(activity, TestTheme.THEME_FEATURE_A); 322 final Resources resources = activity.getResources(); 323 assertThat(resources, notNullValue()); 324 325 assertThat(resources.getString(R.string.base_string), equalTo("Base String Default")); 326 new TestTheme(activity, R.style.Theme_Base).assertThemeBaseValues(); 327 328 int resourceId = resources.getIdentifier(FEATURE_A_STRING, null, null); 329 assertThat(resources.getString(resourceId), equalTo("Feature A String Diff Revision")); 330 testTheme.assertThemeFeatureAValuesDiffRev(); 331 332 // Test the theme applied to the activity correctly 333 assertActivityThemeApplied(activity, testTheme); 334 assertTextViewBGColor(activity, FEATURE_A_TEXTVIEW_ID, testTheme.mColorBackground); 335 336 assertActivitiesDoNotExist(activity, FEATURE_B_ACTIVITY, FEATURE_C_ACTIVITY); 337 assertResourcesDoNotExist(activity, FEATURE_B_STRING, FEATURE_C_STRING, 338 TestTheme.THEME_FEATURE_B, TestTheme.THEME_FEATURE_C); 339 } 340 341 @Test shouldLoadFeatureAAndBAndCReceivers()342 public void shouldLoadFeatureAAndBAndCReceivers() throws Exception { 343 final Context context = mAppContextTestRule.getContext(); 344 final ExtrasResultReceiver receiver = sendOrderedBroadcast(context); 345 final Bundle results = receiver.get(); 346 assertThat(results.getString("base"), equalTo("Base String Default")); 347 assertThat(results.getString("feature_a"), equalTo("Feature A String Default")); 348 assertThat(results.getString("feature_b"), equalTo("Feature B String Default")); 349 assertThat(results.getString("feature_c"), equalTo("Feature C String Default")); 350 } 351 352 @Test shouldNotFoundFeatureC()353 public void shouldNotFoundFeatureC() throws Exception { 354 assertActivityDoNotExist(FEATURE_C_ACTIVITY); 355 } 356 357 @Test testNativeJni_shouldBeLoaded()358 public void testNativeJni_shouldBeLoaded() throws Exception { 359 assertThat(Native.add(7, 11), equalTo(18)); 360 } 361 362 @Test testNativeSplit_withoutExtractLibs_nativeLibraryCannotBeLoaded()363 public void testNativeSplit_withoutExtractLibs_nativeLibraryCannotBeLoaded() throws Exception { 364 final Intent intent = new Intent(); 365 intent.setClassName(PACKAGE, "com.android.cts.isolatedsplitapp.jni.JniActivity"); 366 mActivityRule.launchActivity(intent); 367 mActivityRule.finishActivity(); 368 Instrumentation.ActivityResult result = mActivityRule.getActivityResult(); 369 final Intent resultData = result.getResultData(); 370 final String errorMessage = resultData.getStringExtra(Intent.EXTRA_RETURN_RESULT); 371 assertThat(errorMessage, containsString("dlopen failed")); 372 } 373 374 @Test testNative_getNumberADirectly_shouldBeSeven()375 public void testNative_getNumberADirectly_shouldBeSeven() throws Exception { 376 assertThat(Native.getNumberADirectly(), equalTo(7)); 377 } 378 379 @Test testNative_getNumberAViaProxy_shouldBeSeven()380 public void testNative_getNumberAViaProxy_shouldBeSeven() throws Exception { 381 assertThat(Native.getNumberAViaProxy(), equalTo(7)); 382 } 383 384 @Test testNative_getNumberBDirectly_shouldBeEleven()385 public void testNative_getNumberBDirectly_shouldBeEleven() throws Exception { 386 assertThat(Native.getNumberBDirectly(), equalTo(11)); 387 } 388 389 @Test testNative_getNumberBViaProxy_shouldBeEleven()390 public void testNative_getNumberBViaProxy_shouldBeEleven() throws Exception { 391 assertThat(Native.getNumberBViaProxy(), equalTo(11)); 392 } 393 394 @Test testNative_cannotLoadSharedLibrary()395 public void testNative_cannotLoadSharedLibrary() throws Exception { 396 assertThat(Native.isLoadedLibrary(), equalTo(false)); 397 } 398 assertActivityDoNotExist(ComponentName activity)399 private void assertActivityDoNotExist(ComponentName activity) { 400 try { 401 mActivityRule.launchActivity(new Intent().setComponent(activity)); 402 fail("Activity " + activity + " is accessible"); 403 } catch (RuntimeException e) { 404 // Pass. 405 } 406 } 407 assertActivitiesDoNotExist(Context context, ComponentName... activities)408 private static void assertActivitiesDoNotExist(Context context, ComponentName... activities) { 409 for (ComponentName activity : activities) { 410 try { 411 Class.forName(activity.getClassName(), true, context.getClassLoader()); 412 fail("Class " + activity.getClassName() + " is accessible"); 413 } catch (ClassNotFoundException e) { 414 // Pass. 415 } 416 } 417 } 418 assertResourcesDoNotExist(Context context, String... resourceNames)419 private static void assertResourcesDoNotExist(Context context, String... resourceNames) { 420 final Resources resources = context.getResources(); 421 for (String resourceName : resourceNames) { 422 final int resid = resources.getIdentifier(resourceName, null, null); 423 if (resid != 0) { 424 fail("Found resource '" + resourceName + "' with ID " + Integer.toHexString(resid)); 425 } 426 } 427 } 428 assertActivityThemeApplied(Activity activity, TestTheme testTheme)429 private static void assertActivityThemeApplied(Activity activity, TestTheme testTheme) { 430 assertBaseLayoutBGColor(activity, testTheme.mBaseColor); 431 assertThat(activity.getWindow().getStatusBarColor(), equalTo(testTheme.mStatusBarColor)); 432 assertThat(activity.getWindow().getNavigationBarColor(), 433 equalTo(testTheme.mNavigationBarColor)); 434 assertDrawableColor(activity.getWindow().getDecorView().getBackground(), 435 testTheme.mWindowBackground); 436 } 437 assertBaseLayoutBGColor(Activity activity, int expected)438 private static void assertBaseLayoutBGColor(Activity activity, int expected) { 439 final LinearLayout layout = activity.findViewById(R.id.base_layout); 440 final Drawable background = layout.getBackground(); 441 assertDrawableColor(background, expected); 442 } 443 assertTextViewBGColor(Activity activity, String nameOfIdentifier, int expected)444 private static void assertTextViewBGColor(Activity activity, String nameOfIdentifier, 445 int expected) { 446 final int viewId = activity.getResources().getIdentifier(nameOfIdentifier, null, null); 447 assertThat(viewId, not(equalTo(0))); 448 449 final View view = activity.findViewById(viewId); 450 final Drawable background = view.getBackground(); 451 assertDrawableColor(background, expected); 452 } 453 assertDrawableColor(Drawable drawable, int expected)454 private static void assertDrawableColor(Drawable drawable, int expected) { 455 int color = 0; 456 if (drawable instanceof ColorDrawable) { 457 color = ((ColorDrawable) drawable).getColor(); 458 } else { 459 fail("Can't get drawable color"); 460 } 461 assertThat(color, equalTo(expected)); 462 } 463 464 private static class ExtrasResultReceiver extends BroadcastReceiver { 465 private final CompletableFuture<Bundle> mResult = new CompletableFuture<>(); 466 467 @Override onReceive(Context context, Intent intent)468 public void onReceive(Context context, Intent intent) { 469 mResult.complete(getResultExtras(true)); 470 } 471 get()472 public Bundle get() throws Exception { 473 return mResult.get(5000, TimeUnit.SECONDS); 474 } 475 } 476 sendOrderedBroadcast(Context context)477 private static ExtrasResultReceiver sendOrderedBroadcast(Context context) { 478 final ExtrasResultReceiver resultReceiver = new ExtrasResultReceiver(); 479 context.sendOrderedBroadcast(new Intent(PACKAGE + ".ACTION").setPackage(PACKAGE), null, 480 resultReceiver, null, 0, null, null); 481 return resultReceiver; 482 } 483 484 private static class AppContextTestRule implements TestRule { 485 private Context mContext; 486 487 @Override apply(final Statement base, Description description)488 public Statement apply(final Statement base, Description description) { 489 return new Statement() { 490 @Override 491 public void evaluate() throws Throwable { 492 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 493 base.evaluate(); 494 } 495 }; 496 } 497 getContext()498 public Context getContext() { 499 return mContext; 500 } 501 } 502 } 503