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.om;
18 
19 import static android.content.om.OverlayInfo.STATE_DISABLED;
20 import static android.content.om.OverlayInfo.STATE_ENABLED;
21 import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
22 import static android.os.OverlayablePolicy.CONFIG_SIGNATURE;
23 
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertNotNull;
27 import static org.junit.Assert.assertNull;
28 import static org.junit.Assert.assertTrue;
29 import static org.testng.Assert.assertThrows;
30 
31 import android.content.om.OverlayIdentifier;
32 import android.content.om.OverlayInfo;
33 import android.util.Pair;
34 
35 import androidx.test.runner.AndroidJUnit4;
36 
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Optional;
43 import java.util.Set;
44 
45 @RunWith(AndroidJUnit4.class)
46 public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase {
47 
48     private static final String OVERLAY = "com.test.overlay";
49     private static final OverlayIdentifier IDENTIFIER = new OverlayIdentifier(OVERLAY);
50     private static final String TARGET = "com.test.target";
51     private static final int USER = 0;
52 
53     private static final String OVERLAY2 = OVERLAY + "2";
54     private static final String TARGET2 = TARGET + "2";
55     private static final OverlayIdentifier IDENTIFIER2 = new OverlayIdentifier(OVERLAY2);
56     private static final int USER2 = USER + 1;
57 
58     private static final String OVERLAY3 = OVERLAY + "3";
59     private static final OverlayIdentifier IDENTIFIER3 = new OverlayIdentifier(OVERLAY3);
60     private static final int USER3 = USER2 + 1;
61 
62     private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.test.ref";
63     private static final String CERT_CONFIG_OK = "config_certificate_ok";
64     private static final String CERT_CONFIG_NOK = "config_certificate_nok";
65 
66     @Test
testGetOverlayInfo()67     public void testGetOverlayInfo() throws Exception {
68         installAndAssert(overlay(OVERLAY, TARGET), USER,
69                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
70 
71         final OverlayManagerServiceImpl impl = getImpl();
72         final OverlayInfo oi = impl.getOverlayInfo(IDENTIFIER, USER);
73         assertNotNull(oi);
74         assertEquals(oi.packageName, OVERLAY);
75         assertEquals(oi.targetPackageName, TARGET);
76         assertEquals(oi.userId, USER);
77     }
78 
79     @Test
testGetOverlayInfosForTarget()80     public void testGetOverlayInfosForTarget() throws Exception {
81         installAndAssert(overlay(OVERLAY, TARGET), USER,
82                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
83         installAndAssert(overlay(OVERLAY2, TARGET), USER,
84                 Set.of(new PackageAndUser(OVERLAY2, USER), new PackageAndUser(TARGET, USER)));
85         installAndAssert(overlay(OVERLAY3, TARGET), USER2,
86                 Set.of(new PackageAndUser(OVERLAY3, USER2), new PackageAndUser(TARGET, USER2)));
87 
88         final OverlayManagerServiceImpl impl = getImpl();
89         final List<OverlayInfo> ois = impl.getOverlayInfosForTarget(TARGET, USER);
90         assertEquals(ois.size(), 2);
91         assertTrue(ois.contains(impl.getOverlayInfo(IDENTIFIER, USER)));
92         assertTrue(ois.contains(impl.getOverlayInfo(IDENTIFIER2, USER)));
93 
94         final List<OverlayInfo> ois2 = impl.getOverlayInfosForTarget(TARGET, USER2);
95         assertEquals(ois2.size(), 1);
96         assertTrue(ois2.contains(impl.getOverlayInfo(IDENTIFIER3, USER2)));
97 
98         final List<OverlayInfo> ois3 = impl.getOverlayInfosForTarget(TARGET, USER3);
99         assertNotNull(ois3);
100         assertEquals(ois3.size(), 0);
101 
102         final List<OverlayInfo> ois4 = impl.getOverlayInfosForTarget("no.such.overlay", USER);
103         assertNotNull(ois4);
104         assertEquals(ois4.size(), 0);
105     }
106 
107     @Test
testGetOverlayInfosForUser()108     public void testGetOverlayInfosForUser() throws Exception {
109         installAndAssert(target(TARGET), USER,
110                 Set.of(new PackageAndUser(TARGET, USER)));
111         installAndAssert(overlay(OVERLAY, TARGET), USER,
112                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
113         installAndAssert(overlay(OVERLAY2, TARGET), USER,
114                 Set.of(new PackageAndUser(OVERLAY2, USER), new PackageAndUser(TARGET, USER)));
115         installAndAssert(overlay(OVERLAY3, TARGET2), USER,
116                 Set.of(new PackageAndUser(OVERLAY3, USER), new PackageAndUser(TARGET2, USER)));
117 
118         final OverlayManagerServiceImpl impl = getImpl();
119         final Map<String, List<OverlayInfo>> everything = impl.getOverlaysForUser(USER);
120         assertEquals(everything.size(), 2);
121 
122         final List<OverlayInfo> ois = everything.get(TARGET);
123         assertNotNull(ois);
124         assertEquals(ois.size(), 2);
125         assertTrue(ois.contains(impl.getOverlayInfo(IDENTIFIER, USER)));
126         assertTrue(ois.contains(impl.getOverlayInfo(IDENTIFIER2, USER)));
127 
128         final List<OverlayInfo> ois2 = everything.get(TARGET2);
129         assertNotNull(ois2);
130         assertEquals(ois2.size(), 1);
131         assertTrue(ois2.contains(impl.getOverlayInfo(IDENTIFIER3, USER)));
132 
133         final Map<String, List<OverlayInfo>> everything2 = impl.getOverlaysForUser(USER2);
134         assertNotNull(everything2);
135         assertEquals(everything2.size(), 0);
136     }
137 
138     @Test
testPriority()139     public void testPriority() throws Exception {
140         installAndAssert(overlay(OVERLAY, TARGET), USER,
141                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
142         installAndAssert(overlay(OVERLAY2, TARGET), USER,
143                 Set.of(new PackageAndUser(OVERLAY2, USER), new PackageAndUser(TARGET, USER)));
144         installAndAssert(overlay(OVERLAY3, TARGET), USER,
145                 Set.of(new PackageAndUser(OVERLAY3, USER), new PackageAndUser(TARGET, USER)));
146 
147         final OverlayManagerServiceImpl impl = getImpl();
148         final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
149         final OverlayInfo o2 = impl.getOverlayInfo(IDENTIFIER2, USER);
150         final OverlayInfo o3 = impl.getOverlayInfo(IDENTIFIER3, USER);
151 
152         assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
153 
154         assertEquals(impl.setLowestPriority(IDENTIFIER3, USER),
155                 Optional.of(new PackageAndUser(TARGET, USER)));
156         assertOverlayInfoForTarget(TARGET, USER, o3, o1, o2);
157 
158         assertEquals(impl.setHighestPriority(IDENTIFIER3, USER),
159                 Set.of(new PackageAndUser(TARGET, USER)));
160         assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
161 
162         assertEquals(impl.setPriority(IDENTIFIER, IDENTIFIER2, USER),
163                 Optional.of(new PackageAndUser(TARGET, USER)));
164         assertOverlayInfoForTarget(TARGET, USER, o2, o1, o3);
165     }
166 
167     @Test
testOverlayInfoStateTransitions()168     public void testOverlayInfoStateTransitions() throws Exception {
169         final OverlayManagerServiceImpl impl = getImpl();
170         assertNull(impl.getOverlayInfo(IDENTIFIER, USER));
171 
172         installAndAssert(overlay(OVERLAY, TARGET), USER,
173                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
174         assertState(STATE_MISSING_TARGET, IDENTIFIER, USER);
175 
176         installAndAssert(target(TARGET), USER,
177                 Set.of(new PackageAndUser(TARGET, USER)));
178         assertState(STATE_DISABLED, IDENTIFIER, USER);
179 
180         assertEquals(impl.setEnabled(IDENTIFIER, true, USER),
181                 Set.of(new PackageAndUser(TARGET, USER)));
182         assertState(STATE_ENABLED, IDENTIFIER, USER);
183 
184         // target upgrades do not change the state of the overlay
185         upgradeAndAssert(target(TARGET), USER,
186                 Set.of(new PackageAndUser(TARGET, USER)),
187                 Set.of(new PackageAndUser(TARGET, USER)));
188         assertState(STATE_ENABLED, IDENTIFIER, USER);
189 
190         uninstallAndAssert(TARGET, USER,
191                 Set.of(new PackageAndUser(TARGET, USER)));
192         assertState(STATE_MISSING_TARGET, IDENTIFIER, USER);
193 
194         installAndAssert(target(TARGET), USER,
195                 Set.of(new PackageAndUser(TARGET, USER)));
196         assertState(STATE_ENABLED, IDENTIFIER, USER);
197     }
198 
199     @Test
testOnOverlayPackageUpgraded()200     public void testOnOverlayPackageUpgraded() throws Exception {
201         installAndAssert(target(TARGET), USER,
202                 Set.of(new PackageAndUser(TARGET, USER)));
203         installAndAssert(overlay(OVERLAY, TARGET), USER,
204                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
205         upgradeAndAssert(overlay(OVERLAY, TARGET), USER,
206                 Set.of(new PackageAndUser(TARGET, USER)),
207                 Set.of(new PackageAndUser(TARGET, USER)));
208 
209         // upgrade to a version where the overlay has changed its target
210         upgradeAndAssert(overlay(OVERLAY, TARGET2), USER,
211                 Set.of(new PackageAndUser(TARGET, USER)),
212                 Set.of(new PackageAndUser(TARGET, USER),
213                         new PackageAndUser(TARGET2, USER)));
214     }
215 
216     @Test
testSetEnabledAtVariousConditions()217     public void testSetEnabledAtVariousConditions() throws Exception {
218         final OverlayManagerServiceImpl impl = getImpl();
219         assertThrows(OverlayManagerServiceImpl.OperationFailedException.class,
220                 () -> impl.setEnabled(IDENTIFIER, true, USER));
221 
222         // request succeeded, and there was a change that needs to be
223         // propagated to the rest of the system
224         installAndAssert(target(TARGET), USER,
225                 Set.of(new PackageAndUser(TARGET, USER)));
226         installAndAssert(overlay(OVERLAY, TARGET), USER,
227                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
228         assertEquals(Set.of(new PackageAndUser(TARGET, USER)),
229                 impl.setEnabled(IDENTIFIER, true, USER));
230 
231         // request succeeded, but nothing changed
232         assertEquals(Set.of(), impl.setEnabled(IDENTIFIER, true, USER));
233     }
234 
235     @Test
testConfigSignaturePolicyOk()236     public void testConfigSignaturePolicyOk() throws Exception {
237         setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
238         reinitializeImpl();
239 
240         addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
241         installAndAssert(target(TARGET), USER,
242                 Set.of(new PackageAndUser(TARGET, USER)));
243         installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER,
244                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
245 
246         final FakeIdmapDaemon idmapd = getIdmapd();
247         final FakeDeviceState state = getState();
248         final String overlayPath = state.select(OVERLAY, USER).apkPath;
249         assertTrue(idmapd.idmapExists(overlayPath, USER));
250 
251         final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
252         assertEquals(CONFIG_SIGNATURE, CONFIG_SIGNATURE & idmap.policies);
253     }
254 
255     @Test
testConfigSignaturePolicyCertNok()256     public void testConfigSignaturePolicyCertNok() throws Exception {
257         setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
258         reinitializeImpl();
259 
260         addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
261         installAndAssert(target(TARGET), USER,
262                 Set.of(new PackageAndUser(TARGET, USER)));
263         installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
264                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
265 
266         final FakeIdmapDaemon idmapd = getIdmapd();
267         final FakeDeviceState state = getState();
268         final String overlayPath = state.select(OVERLAY, USER).apkPath;
269         assertTrue(idmapd.idmapExists(overlayPath, USER));
270 
271         final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
272         assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
273     }
274 
275     @Test
testConfigSignaturePolicyNoConfig()276     public void testConfigSignaturePolicyNoConfig() throws Exception {
277         addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
278         installAndAssert(target(TARGET), USER,
279                 Set.of(new PackageAndUser(TARGET, USER)));
280         installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
281                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
282 
283         final FakeIdmapDaemon idmapd = getIdmapd();
284         final FakeDeviceState state = getState();
285         final String overlayPath = state.select(OVERLAY, USER).apkPath;
286         assertTrue(idmapd.idmapExists(overlayPath, USER));
287 
288         final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
289         assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
290     }
291 
292     @Test
testConfigSignaturePolicyNoRefPkg()293     public void testConfigSignaturePolicyNoRefPkg() throws Exception {
294         installAndAssert(target(TARGET), USER,
295                 Set.of(new PackageAndUser(TARGET, USER)));
296         installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
297                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
298 
299         final FakeIdmapDaemon idmapd = getIdmapd();
300         final FakeDeviceState state = getState();
301         final String overlayPath = state.select(OVERLAY, USER).apkPath;
302         assertTrue(idmapd.idmapExists(overlayPath, USER));
303 
304         final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
305         assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
306     }
307 
308     @Test
testConfigSignaturePolicyRefPkgNotSystem()309     public void testConfigSignaturePolicyRefPkgNotSystem() throws Exception {
310         setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
311         reinitializeImpl();
312 
313         addPackage(app(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
314         installAndAssert(target(TARGET), USER,
315                 Set.of(new PackageAndUser(TARGET, USER)));
316         installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
317                 Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
318 
319         final FakeIdmapDaemon idmapd = getIdmapd();
320         final FakeDeviceState state = getState();
321         String overlayPath = state.select(OVERLAY, USER).apkPath;
322         assertTrue(idmapd.idmapExists(overlayPath, USER));
323 
324         FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
325         assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
326     }
327 }
328