Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fcad6968 authored by Jiyong Park's avatar Jiyong Park
Browse files

vendor apk is unbundled

Vendor apks has been regarded as bundled apps and thus provided with all
internal libraries under /system/lib and /vendor/lib. However, in new
devices where Treble is fully enabled, system and vendor partitions are
no longer bundled together; system partition can be updated
independently from the vendor partition.

In that case, the apks in vendor partition are considered as unbundled
so that access to /system/lib is limited.

In addition, when the linker namespace is created for apks, information
on whether the apk is in vendor partition or not is given to the
libnativeloader library. The information is used to conditionally
configure the linker namespace for vendors. For examle, vendor apks are
allowed to access /vendor/lib even though they are considered as
unbundled; because vendor apks and vendor libs are still bundled
together in the same vendor partition.

Bug: 63553457
Test: 1) set target as 2017 pixel
2) m -j CtsVendorJniTestCases
3) copy the built apk into /vendor/app/CtsVendorJniTestCases
4) reboot / factory reset
5) adb shell am instrument -w android.jni.vendor.cts

Change-Id: Iadd34af2878c507d4d6ec50153abef4e65604ac9
parent b6a1c5f0
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -625,17 +625,29 @@ public final class LoadedApk {
        final List<String> zipPaths = new ArrayList<>(10);
        final List<String> libPaths = new ArrayList<>(10);

        final boolean isBundledApp = mApplicationInfo.isSystemApp()
        boolean isBundledApp = mApplicationInfo.isSystemApp()
                && !mApplicationInfo.isUpdatedSystemApp();

        // Vendor apks are treated as bundled only when /vendor/lib is in the default search
        // paths. If not, they are treated as unbundled; access to system libs is limited.
        // Having /vendor/lib in the default search paths means that all system processes
        // are allowed to use any vendor library, which in turn means that system is dependent
        // on vendor partition. In the contrary, not having /vendor/lib in the default search
        // paths mean that the two partitions are separated and thus we can treat vendor apks
        // as unbundled.
        final String defaultSearchPaths = System.getProperty("java.library.path");
        final boolean treatVendorApkAsUnbundled = !defaultSearchPaths.contains("/vendor/lib");
        if (mApplicationInfo.getCodePath().startsWith("/vendor/") && treatVendorApkAsUnbundled) {
            isBundledApp = false;
        }

        makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths);

        String libraryPermittedPath = mDataDir;
        if (isBundledApp) {
            // This is necessary to grant bundled apps access to
            // libraries located in subdirectories of /system/lib
            libraryPermittedPath += File.pathSeparator +
                                    System.getProperty("java.library.path");
            libraryPermittedPath += File.pathSeparator + defaultSearchPaths;
        }

        final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
+11 −2
Original line number Diff line number Diff line
@@ -88,12 +88,20 @@ public class ClassLoaderFactory {
        final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
                classloaderName);

        boolean isForVendor = false;
        for (String path : dexPath.split(":")) {
            if (path.startsWith("/vendor/")) {
                isForVendor = true;
                break;
            }
        }
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
        String errorMessage = createClassloaderNamespace(classLoader,
                                                         targetSdkVersion,
                                                         librarySearchPath,
                                                         libraryPermittedPath,
                                                         isNamespaceShared);
                                                         isNamespaceShared,
                                                         isForVendor);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        if (errorMessage != null) {
@@ -108,5 +116,6 @@ public class ClassLoaderFactory {
                                                            int targetSdkVersion,
                                                            String librarySearchPath,
                                                            String libraryPermittedPath,
                                                            boolean isNamespaceShared);
                                                            boolean isNamespaceShared,
                                                            boolean isForVendor);
}
+4 −2
Original line number Diff line number Diff line
@@ -27,15 +27,17 @@ static jstring createClassloaderNamespace_native(JNIEnv* env,
                                              jint targetSdkVersion,
                                              jstring librarySearchPath,
                                              jstring libraryPermittedPath,
                                              jboolean isShared) {
                                              jboolean isShared,
                                              jboolean isForVendor) {
    return android::CreateClassLoaderNamespace(env, targetSdkVersion,
                                               classLoader, isShared == JNI_TRUE,
                                               isForVendor == JNI_TRUE,
                                               librarySearchPath, libraryPermittedPath);
}

static const JNINativeMethod g_methods[] = {
    { "createClassloaderNamespace",
      "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
      "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZZ)Ljava/lang/String;",
      reinterpret_cast<void*>(createClassloaderNamespace_native) },
};