1 /*
2  * Copyright (C) 2024 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 android.test.lib;
18 
19 import android.test.productsharedlib.ProductSharedLib;
20 import android.test.systemextsharedlib.SystemExtSharedLib;
21 import android.test.systemsharedlib.SystemSharedLib;
22 import android.test.vendorsharedlib.VendorSharedLib;
23 
24 import androidx.test.runner.AndroidJUnit4;
25 
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 
29 @RunWith(AndroidJUnit4.class)
30 public abstract class AppTestCommon {
31     public enum AppLocation { DATA, SYSTEM, PRODUCT, VENDOR }
32 
getAppLocation()33     public abstract AppLocation getAppLocation();
34 
35     // Loading private libs using absolute paths through shared libs should
36     // normally only depend on the location of the shared lib, so these tests
37     // are shared for all apps, regardless of location.
38 
39     // Returns true when system private native libs are accessible directly from
40     // the app classloader namespace.
systemPrivateLibsAccessibleFromAppNamespace()41     private boolean systemPrivateLibsAccessibleFromAppNamespace() {
42         // Currently it only works from system apps. It also works from product
43         // apps on old versions where they were treated like system apps.
44         return getAppLocation() == AppLocation.SYSTEM
45                 || (getAppLocation() == AppLocation.PRODUCT && TestUtils.productAppsAreShared());
46     }
47 
48     // Detect exception when product private libs are accessible directly from
49     // the app classloader namespace even when they shouldn't be.
productPrivateLibsAccessibleFromAppNamespace()50     private boolean productPrivateLibsAccessibleFromAppNamespace() {
51         // In old versions where product apps were treated like system apps, the
52         // product private libs were included in the system namespace, so
53         // they're accessible both from system and product apps.
54         return (getAppLocation() == AppLocation.SYSTEM || getAppLocation() == AppLocation.PRODUCT)
55                 && TestUtils.productAppsAreShared();
56     }
57 
58     // Detect exception where we don't switch from a shared system namespace to
59     // a product or vendor "unbundled" namespace when calling into
60     // ProductSharedLib and VendorSharedLib. That means they still can load
61     // private system libs but not private libs in their own partition (however
62     // the latter works anyway when canLoadPrivateLibsFromSamePartition() is
63     // true).
64     // TODO(mast): Stop propagating the shared property (isBundledApp in
65     // LoadedApk.java) down to public and vendor shared java libs?
noSwitchToVendorOrProductNamespace()66     private boolean noSwitchToVendorOrProductNamespace() {
67         // System apps get shared namespaces, and also product apps on old
68         // versions where they were treated like system apps.
69         return getAppLocation() == AppLocation.SYSTEM
70                 || (getAppLocation() == AppLocation.PRODUCT && TestUtils.productAppsAreShared());
71     }
72 
73     @Test
testLoadPrivateLibrariesViaSystemSharedLibWithAbsolutePaths()74     public void testLoadPrivateLibrariesViaSystemSharedLibWithAbsolutePaths() {
75         if (TestUtils.canLoadPrivateLibsFromSamePartition()
76                 || systemPrivateLibsAccessibleFromAppNamespace()) {
77             SystemSharedLib.load(TestUtils.libPath("/system", "system_private7"));
78             SystemSharedLib.load(TestUtils.libPath("/system_ext", "systemext_private7"));
79         } else {
80             TestUtils.assertLibraryInaccessible(() -> {
81                 SystemSharedLib.load(TestUtils.libPath("/system", "system_private7"));
82             });
83             TestUtils.assertLibraryInaccessible(() -> {
84                 SystemSharedLib.load(TestUtils.libPath("/system_ext", "systemext_private7"));
85             });
86         }
87 
88         if (productPrivateLibsAccessibleFromAppNamespace()) {
89             SystemSharedLib.load(TestUtils.libPath("/product", "product_private7"));
90         } else {
91             TestUtils.assertLibraryInaccessible(() -> {
92                 SystemSharedLib.load(TestUtils.libPath("/product", "product_private7"));
93             });
94         }
95 
96         TestUtils.assertLibraryInaccessible(
97                 () -> { SystemSharedLib.load(TestUtils.libPath("/vendor", "vendor_private7")); });
98     }
99 
100     @Test
testLoadPrivateLibrariesViaSystemExtSharedLibWithAbsolutePaths()101     public void testLoadPrivateLibrariesViaSystemExtSharedLibWithAbsolutePaths() {
102         if (TestUtils.canLoadPrivateLibsFromSamePartition()
103                 || systemPrivateLibsAccessibleFromAppNamespace()) {
104             SystemExtSharedLib.load(TestUtils.libPath("/system", "system_private8"));
105             SystemExtSharedLib.load(TestUtils.libPath("/system_ext", "systemext_private8"));
106         } else {
107             TestUtils.assertLibraryInaccessible(() -> {
108                 SystemExtSharedLib.load(TestUtils.libPath("/system", "system_private8"));
109             });
110             TestUtils.assertLibraryInaccessible(() -> {
111                 SystemExtSharedLib.load(TestUtils.libPath("/system_ext", "systemext_private8"));
112             });
113         }
114 
115         if (productPrivateLibsAccessibleFromAppNamespace()) {
116             SystemExtSharedLib.load(TestUtils.libPath("/product", "product_private8"));
117         } else {
118             TestUtils.assertLibraryInaccessible(() -> {
119                 SystemExtSharedLib.load(TestUtils.libPath("/product", "product_private8"));
120             });
121         }
122 
123         TestUtils.assertLibraryInaccessible(() -> {
124             SystemExtSharedLib.load(TestUtils.libPath("/vendor", "vendor_private8"));
125         });
126     }
127 
128     @Test
testLoadPrivateLibrariesViaProductSharedLibWithAbsolutePaths()129     public void testLoadPrivateLibrariesViaProductSharedLibWithAbsolutePaths() {
130         if (systemPrivateLibsAccessibleFromAppNamespace() || noSwitchToVendorOrProductNamespace()) {
131             ProductSharedLib.load(TestUtils.libPath("/system", "system_private9"));
132             ProductSharedLib.load(TestUtils.libPath("/system_ext", "systemext_private9"));
133         } else {
134             TestUtils.assertLibraryInaccessible(() -> {
135                 ProductSharedLib.load(TestUtils.libPath("/system", "system_private9"));
136             });
137             TestUtils.assertLibraryInaccessible(() -> {
138                 ProductSharedLib.load(TestUtils.libPath("/system_ext", "systemext_private9"));
139             });
140         }
141 
142         boolean loadPrivateProductLib;
143         if (TestUtils.productAppsAreShared()) {
144             // The library is accessible if the app is in either system or
145             // product, because both are loaded as system apps and private product
146             // libs are available for both.
147             loadPrivateProductLib = getAppLocation() == AppLocation.SYSTEM
148                     || getAppLocation() == AppLocation.PRODUCT;
149         } else {
150             loadPrivateProductLib = TestUtils.canLoadPrivateLibsFromSamePartition()
151                     || !noSwitchToVendorOrProductNamespace();
152         }
153         if (loadPrivateProductLib) {
154             ProductSharedLib.load(TestUtils.libPath("/product", "product_private9"));
155         } else {
156             TestUtils.assertLibraryInaccessible(() -> {
157                 ProductSharedLib.load(TestUtils.libPath("/product", "product_private9"));
158             });
159         }
160 
161         TestUtils.assertLibraryInaccessible(
162                 () -> { ProductSharedLib.load(TestUtils.libPath("/vendor", "vendor_private9")); });
163     }
164 
165     @Test
testLoadPrivateLibrariesViaVendorSharedLibWithAbsolutePaths()166     public void testLoadPrivateLibrariesViaVendorSharedLibWithAbsolutePaths() {
167         if (systemPrivateLibsAccessibleFromAppNamespace() || noSwitchToVendorOrProductNamespace()) {
168             VendorSharedLib.load(TestUtils.libPath("/system", "system_private10"));
169             VendorSharedLib.load(TestUtils.libPath("/system_ext", "systemext_private10"));
170         } else {
171             TestUtils.assertLibraryInaccessible(() -> {
172                 VendorSharedLib.load(TestUtils.libPath("/system", "system_private10"));
173             });
174             TestUtils.assertLibraryInaccessible(() -> {
175                 VendorSharedLib.load(TestUtils.libPath("/system_ext", "systemext_private10"));
176             });
177         }
178 
179         if (productPrivateLibsAccessibleFromAppNamespace()) {
180             VendorSharedLib.load(TestUtils.libPath("/product", "product_private10"));
181         } else {
182             TestUtils.assertLibraryInaccessible(() -> {
183                 VendorSharedLib.load(TestUtils.libPath("/product", "product_private10"));
184             });
185         }
186 
187         if (TestUtils.canLoadPrivateLibsFromSamePartition()
188                 || !noSwitchToVendorOrProductNamespace()) {
189             VendorSharedLib.load(TestUtils.libPath("/vendor", "vendor_private10"));
190         } else {
191             TestUtils.assertLibraryInaccessible(() -> {
192                 VendorSharedLib.load(TestUtils.libPath("/vendor", "vendor_private10"));
193             });
194         }
195     }
196 }
197