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 package com.android.cts.overlay.app;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertThrows;
20 import static org.junit.Assert.assertTrue;
21 
22 import android.content.Context;
23 import android.content.res.AssetFileDescriptor;
24 
25 import androidx.test.InstrumentationRegistry;
26 import androidx.test.runner.AndroidJUnit4;
27 
28 import java.io.InputStreamReader;
29 import java.util.Objects;
30 import java.util.concurrent.Executor;
31 import java.util.concurrent.FutureTask;
32 import java.util.concurrent.TimeUnit;
33 
34 import org.junit.Before;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 
38 @RunWith(AndroidJUnit4.class)
39 public class OverlayableTest {
40     private static final String TARGET_PACKAGE = "com.android.cts.overlay.target";
41 
42     private static final String POLICY_ALL_PACKAGE = "com.android.cts.overlay.all";
43 
44     private static final String OVERLAID = "You have been overlaid";
45     private static final String NOT_OVERLAID = "Not overlaid";
46 
47     private static final long TIMEOUT = 30;
48 
49     private static class R {
50         class string {
51             private static final int not_overlayable = 0x7f010000;
52             private static final int policy_product = 0x7f010001;
53             private static final int policy_public = 0x7f010002;
54             private static final int policy_system = 0x7f010003;
55             private static final int policy_vendor = 0x7f010004;
56             private static final int policy_signature = 0x7f010005;
57             private static final int other_policy_public = 0x7f010006;
58         }
59     }
60 
61     private Executor mExecutor;
62 
63     @Before
setUp()64     public void setUp() throws Exception {
65         mExecutor = (command) -> new Thread(command).start();
66     }
67 
getTargetContext()68     private Context getTargetContext() throws Exception {
69         return InstrumentationRegistry.getTargetContext().createPackageContext(TARGET_PACKAGE, 0);
70     }
71 
assertOverlayEnabled(String overlayPackage)72     private void assertOverlayEnabled(String overlayPackage) throws Exception {
73         // Wait for the overlay changes to propagate
74         FutureTask<Boolean> task = new FutureTask<>(() -> {
75             while (true) {
76                 Context context = getTargetContext();
77                 for (String path : context.getAssets().getApkPaths()) {
78                     if (path.contains(overlayPackage)) {
79                         return true;
80                     }
81                 }
82             }
83         });
84 
85         mExecutor.execute(task);
86         assertTrue("Failed to load overlay " + overlayPackage, task.get(TIMEOUT, TimeUnit.SECONDS));
87     }
88 
89     @Test
testOverlayPolicyAll()90     public void testOverlayPolicyAll() throws Exception {
91         assertOverlayEnabled(POLICY_ALL_PACKAGE);
92         Context context = getTargetContext();
93 
94         String result = context.getResources().getString(R.string.not_overlayable);
95         assertEquals(NOT_OVERLAID, result);
96 
97         result = context.getResources().getString(R.string.policy_public);
98         assertEquals(OVERLAID, result);
99 
100         result = context.getResources().getString(R.string.policy_product);
101         assertEquals(NOT_OVERLAID, result);
102 
103         result = context.getResources().getString(R.string.policy_system);
104         assertEquals(NOT_OVERLAID, result);
105 
106         result = context.getResources().getString(R.string.policy_vendor);
107         assertEquals(NOT_OVERLAID, result);
108 
109         result = context.getResources().getString(R.string.policy_signature);
110         assertEquals(OVERLAID, result);
111 
112         result = context.getResources().getString(R.string.other_policy_public);
113         assertEquals(NOT_OVERLAID, result);
114     }
115 
116     @Test
testOverlayCodeNotLoaded()117     public void testOverlayCodeNotLoaded() throws Exception {
118         assertOverlayEnabled(POLICY_ALL_PACKAGE);
119         Context context = getTargetContext();
120 
121         String result = context.getResources().getString(R.string.policy_public);
122         assertEquals(OVERLAID, result);
123 
124         final String overlayClassName = "com.android.cts.overlay.all.InjectedOverlay";
125         assertThrows(ClassNotFoundException.class, () -> Objects.requireNonNull(
126                 getClass().getClassLoader()).loadClass(overlayClassName));
127     }
128 
129     @Test
testSameSignatureNoOverlayableSucceeds()130     public void testSameSignatureNoOverlayableSucceeds() throws Exception {
131         assertOverlayEnabled(POLICY_ALL_PACKAGE);
132         Context context = getTargetContext();
133 
134         String result = context.getResources().getString(R.string.not_overlayable);
135         assertEquals(OVERLAID, result);
136 
137         result = context.getResources().getString(R.string.policy_public);
138         assertEquals(OVERLAID, result);
139 
140         result = context.getResources().getString(R.string.policy_product);
141         assertEquals(OVERLAID, result);
142 
143         result = context.getResources().getString(R.string.policy_system);
144         assertEquals(OVERLAID, result);
145 
146         result = context.getResources().getString(R.string.policy_vendor);
147         assertEquals(OVERLAID, result);
148 
149         result = context.getResources().getString(R.string.policy_signature);
150         assertEquals(OVERLAID, result);
151 
152         result = context.getResources().getString(R.string.other_policy_public);
153         assertEquals(OVERLAID, result);
154     }
155 
156     @Test
testFrameworkDoesNotDefineOverlayable()157     public void testFrameworkDoesNotDefineOverlayable() throws Exception {
158         assertTrue(InstrumentationRegistry.getTargetContext().getAssets().getOverlayablesToString(
159                 "android").isEmpty());
160     }
161 
162     @Test
testCannotOverlayAssets()163     public void testCannotOverlayAssets() throws Exception {
164         Context context = getTargetContext();
165         AssetFileDescriptor d = context.getAssets().openNonAssetFd("assets/asset.txt");
166         InputStreamReader inputStreamReader = new InputStreamReader(d.createInputStream());
167 
168         StringBuilder output = new StringBuilder();
169         for (int c = inputStreamReader.read(); c >= 0; c = inputStreamReader.read()) {
170             output.append((char) c);
171         }
172 
173         assertEquals(NOT_OVERLAID, output.toString());
174     }
175 }