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