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

Commit ddbe50df authored by Kenny Root's avatar Kenny Root
Browse files

Move native libraries to /data/app-lib

Instead of unpacking libraries into /data/data/<appname>/lib, unpack
them into /data/app-lib so that multi-user applications can use the same
libraries.

Change-Id: I636dafb5a9eea8cf5a41f1360698e7695455f385
parent 3c1a2011
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -72,6 +72,8 @@ public class PackageManagerTests extends AndroidTestCase {


    public final long WAIT_TIME_INCR = 5 * 1000;
    public final long WAIT_TIME_INCR = 5 * 1000;


    private static final String APP_LIB_DIR_PREFIX = "/data/app-lib/";

    private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec/";
    private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec/";


    private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO;
    private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO;
@@ -433,7 +435,7 @@ public class PackageManagerTests extends AndroidTestCase {
                    assertEquals(srcPath, appInstallPath);
                    assertEquals(srcPath, appInstallPath);
                    assertEquals(publicSrcPath, appInstallPath);
                    assertEquals(publicSrcPath, appInstallPath);
                    assertStartsWith("Native library should point to shared lib directory",
                    assertStartsWith("Native library should point to shared lib directory",
                            dataDir.getPath(),
                            new File(APP_LIB_DIR_PREFIX, info.packageName).getPath(),
                            info.nativeLibraryDir);
                            info.nativeLibraryDir);
                    assertDirOwnerGroupPerms(
                    assertDirOwnerGroupPerms(
                            "Native library directory should be owned by system:system and 0755",
                            "Native library directory should be owned by system:system and 0755",
+8 −0
Original line number Original line Diff line number Diff line
@@ -359,6 +359,14 @@ class Installer {
        return execute("movefiles");
        return execute("movefiles");
    }
    }


    /**
     * Links the native library directory in an application's directory to its
     * real location.
     *
     * @param dataPath data directory where the application is
     * @param nativeLibPath target native library path
     * @return -1 on error
     */
    public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
    public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
        if (dataPath == null) {
        if (dataPath == null) {
            Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");
            Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");
+137 −44
Original line number Original line Diff line number Diff line
@@ -25,6 +25,11 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.ArrayUtils.removeInt;
import static com.android.internal.util.ArrayUtils.removeInt;
import static libcore.io.OsConstants.S_ISLNK;
import static libcore.io.OsConstants.S_ISLNK;
import static libcore.io.OsConstants.S_IRWXU;
import static libcore.io.OsConstants.S_IRGRP;
import static libcore.io.OsConstants.S_IXGRP;
import static libcore.io.OsConstants.S_IROTH;
import static libcore.io.OsConstants.S_IXOTH;


import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.ResolverActivity;
import com.android.internal.app.ResolverActivity;
@@ -147,6 +152,7 @@ import java.util.Set;
import libcore.io.ErrnoException;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
import libcore.io.IoUtils;
import libcore.io.Libcore;
import libcore.io.Libcore;
import libcore.io.OsConstants;
import libcore.io.StructStat;
import libcore.io.StructStat;


/**
/**
@@ -276,7 +282,7 @@ public class PackageManagerService extends IPackageManager.Stub {
    // This is the object monitoring mDrmAppPrivateInstallDir.
    // This is the object monitoring mDrmAppPrivateInstallDir.
    final FileObserver mDrmAppInstallObserver;
    final FileObserver mDrmAppInstallObserver;


    // Used for priviledge escalation.  MUST NOT BE CALLED WITH mPackages
    // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
    // LOCK HELD.  Can be called with mInstallLock held.
    // LOCK HELD.  Can be called with mInstallLock held.
    final Installer mInstaller;
    final Installer mInstaller;


@@ -286,6 +292,12 @@ public class PackageManagerService extends IPackageManager.Stub {
    final File mAppInstallDir;
    final File mAppInstallDir;
    final File mDalvikCacheDir;
    final File mDalvikCacheDir;


    /**
     * Directory to which applications installed internally have native
     * libraries copied.
     */
    private File mAppLibInstallDir;

    // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
    // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
    // apps.
    // apps.
    final File mDrmAppPrivateInstallDir;
    final File mDrmAppPrivateInstallDir;
@@ -1215,6 +1227,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            }
            }


            mAppInstallDir = new File(dataDir, "app");
            mAppInstallDir = new File(dataDir, "app");
            mAppLibInstallDir = new File(dataDir, "app-lib");
            //look for any incomplete package installations
            //look for any incomplete package installations
            ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
            ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
            //clean up list
            //clean up list
@@ -3607,6 +3620,13 @@ public class PackageManagerService extends IPackageManager.Stub {
                res = resInner;
                res = resInner;
            }
            }
        }
        }

        final File nativeLibraryFile = new File(mAppLibInstallDir, packageName);
        NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
        if (!nativeLibraryFile.delete()) {
            Slog.w(TAG, "Couldn't delete native library directory " + nativeLibraryFile.getPath());
        }

        return res;
        return res;
    }
    }


@@ -4048,9 +4068,7 @@ public class PackageManagerService extends IPackageManager.Stub {
             */
             */
            if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
            if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
                if (pkgSetting.nativeLibraryPathString == null) {
                if (pkgSetting.nativeLibraryPathString == null) {
                    final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath();
                    setInternalAppNativeLibraryPath(pkg, pkgSetting);
                    pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
                    pkgSetting.nativeLibraryPathString = nativeLibraryPath;
                } else {
                } else {
                    pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
                    pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
                }
                }
@@ -4072,7 +4090,7 @@ public class PackageManagerService extends IPackageManager.Stub {
         */
         */
        if (pkg.applicationInfo.nativeLibraryDir != null) {
        if (pkg.applicationInfo.nativeLibraryDir != null) {
            try {
            try {
                final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
                File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
                final String dataPathString = dataPath.getCanonicalPath();
                final String dataPathString = dataPath.getCanonicalPath();


                if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
                if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
@@ -4087,30 +4105,31 @@ public class PackageManagerService extends IPackageManager.Stub {
                        Log.i(TAG, "removed obsolete native libraries for system package "
                        Log.i(TAG, "removed obsolete native libraries for system package "
                                + path);
                                + path);
                    }
                    }
                } else if (nativeLibraryDir.getParentFile().getCanonicalPath()
                } else if (!isForwardLocked(pkg) && !isExternal(pkg)) {
                        .equals(dataPathString)) {
                    // Update native library dir if it starts with /data/data
                    /*
                    if (nativeLibraryDir.getParent().startsWith(dataPathString)) {
                     * Make sure the native library dir isn't a symlink to
                        setInternalAppNativeLibraryPath(pkg, pkgSetting);
                     * something. If it is, ask installd to remove it and create
                        nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
                     * a directory so we can copy to it afterwards.
                    }
                     */

                    boolean isSymLink;
                    try {
                    try {
                        isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode);
                        if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
                    } catch (ErrnoException e) {
                            Slog.e(TAG, "Unable to copy native libraries");
                        // This shouldn't happen, but we'll fail-safe.
                            mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                        isSymLink = true;
                            return null;
                        }
                        }
                    if (isSymLink) {
                    } catch (IOException e) {
                        mInstaller.unlinkNativeLibraryDirectory(dataPathString);
                        Slog.e(TAG, "Unable to copy native libraries", e);
                        mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                        return null;
                    }
                    }


                    /*
                    if (mInstaller.linkNativeLibraryDirectory(dataPathString,
                     * If this is an internal application or our
                            pkg.applicationInfo.nativeLibraryDir) == -1) {
                     * nativeLibraryPath points to our data directory, unpack
                        Slog.e(TAG, "Unable to link native library directory");
                     * the libraries if necessary.
                        mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                     */
                        return null;
                    NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
                    }
                } else {
                } else {
                    Slog.i(TAG, "Linking native library dir for " + path);
                    Slog.i(TAG, "Linking native library dir for " + path);
                    int ret = mInstaller.linkNativeLibraryDirectory(dataPathString,
                    int ret = mInstaller.linkNativeLibraryDirectory(dataPathString,
@@ -4122,7 +4141,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                    }
                    }
                }
                }
            } catch (IOException ioe) {
            } catch (IOException ioe) {
                Log.e(TAG, "Unable to get canonical file " + ioe.toString());
                Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
            }
            }
        }
        }
        pkg.mScanPath = path;
        pkg.mScanPath = path;
@@ -4437,6 +4456,37 @@ public class PackageManagerService extends IPackageManager.Stub {
        return pkg;
        return pkg;
    }
    }


    private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
            PackageSetting pkgSetting) {
        final String apkLibPath = getApkName(pkgSetting.codePathString);
        final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath();
        pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
        pkgSetting.nativeLibraryPathString = nativeLibraryPath;
    }

    private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
            throws IOException {
        if (!nativeLibraryDir.isDirectory()) {
            nativeLibraryDir.delete();
            if (!nativeLibraryDir.mkdir()) {
                throw new IOException("Cannot create " + nativeLibraryDir.getPath());
            }
            try {
                Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH
                        | S_IXOTH);
            } catch (ErrnoException e) {
                throw new IOException("Cannot chmod native library directory "
                        + nativeLibraryDir.getPath(), e);
            }
        }

        /*
         * If this is an internal application or our nativeLibraryPath points to
         * the app-lib directory, unpack the libraries if necessary.
         */
        return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
    }

    private void killApplication(String pkgName, int appId) {
    private void killApplication(String pkgName, int appId) {
        // Request the ActivityManager to kill the process(only for existing packages)
        // Request the ActivityManager to kill the process(only for existing packages)
        // so that we do not end up in a confused state while the user is still using the older
        // so that we do not end up in a confused state while the user is still using the older
@@ -6737,7 +6787,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            String apkName = getNextCodePath(null, pkgName, ".apk");
            String apkName = getNextCodePath(null, pkgName, ".apk");
            codeFileName = new File(installDir, apkName + ".apk").getPath();
            codeFileName = new File(installDir, apkName + ".apk").getPath();
            resourceFileName = getResourcePathFromCodePath();
            resourceFileName = getResourcePathFromCodePath();
            libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
            libraryPath = new File(mAppLibInstallDir, pkgName).getPath();
        }
        }


        boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
        boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
@@ -6774,6 +6824,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
            installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
            codeFileName = createTempPackageFile(installDir).getPath();
            codeFileName = createTempPackageFile(installDir).getPath();
            resourceFileName = getResourcePathFromCodePath();
            resourceFileName = getResourcePathFromCodePath();
            libraryPath = getLibraryPathFromCodePath();
            created = true;
            created = true;
        }
        }


@@ -6828,6 +6879,23 @@ public class PackageManagerService extends IPackageManager.Stub {
                    return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                    return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                }
                }
            }
            }

            final File nativeLibraryFile = new File(getNativeLibraryPath());
            Slog.i(TAG, "Copying native libraries to " + nativeLibraryFile.getPath());
            if (nativeLibraryFile.exists()) {
                NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
                nativeLibraryFile.delete();
            }
            try {
                int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
                if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
                    return copyRet;
                }
            } catch (IOException e) {
                Slog.e(TAG, "Copying native libraries failed", e);
                ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
            }

            return ret;
            return ret;
        }
        }


@@ -6845,6 +6913,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            } else {
            } else {
                final File oldCodeFile = new File(getCodePath());
                final File oldCodeFile = new File(getCodePath());
                final File oldResourceFile = new File(getResourcePath());
                final File oldResourceFile = new File(getResourcePath());
                final File oldLibraryFile = new File(getNativeLibraryPath());


                // Rename APK file based on packageName
                // Rename APK file based on packageName
                final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
                final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
@@ -6859,7 +6928,20 @@ public class PackageManagerService extends IPackageManager.Stub {
                if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
                if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
                    return false;
                    return false;
                }
                }
                resourceFileName = getResourcePathFromCodePath();
                resourceFileName = newResFile.getPath();

                // Rename library path
                final File newLibraryFile = new File(getLibraryPathFromCodePath());
                if (newLibraryFile.exists()) {
                    NativeLibraryHelper.removeNativeBinariesFromDirLI(newLibraryFile);
                    newLibraryFile.delete();
                }
                if (!oldLibraryFile.renameTo(newLibraryFile)) {
                    Slog.e(TAG, "Cannot rename native library directory "
                            + oldLibraryFile.getPath() + " to " + newLibraryFile.getPath());
                    return false;
                }
                libraryPath = newLibraryFile.getPath();


                // Attempt to set permissions
                // Attempt to set permissions
                if (!setPermissions()) {
                if (!setPermissions()) {
@@ -6910,8 +6992,15 @@ public class PackageManagerService extends IPackageManager.Stub {
            }
            }
        }
        }


        private String getLibraryPathFromCodePath() {
            return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath();
        }

        @Override
        @Override
        String getNativeLibraryPath() {
        String getNativeLibraryPath() {
            if (libraryPath == null) {
                libraryPath = getLibraryPathFromCodePath();
            }
            return libraryPath;
            return libraryPath;
        }
        }


@@ -6937,6 +7026,15 @@ public class PackageManagerService extends IPackageManager.Stub {
                    publicSourceFile.delete();
                    publicSourceFile.delete();
                }
                }
            }
            }

            if (libraryPath != null) {
                File nativeLibraryFile = new File(libraryPath);
                NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
                if (!nativeLibraryFile.delete()) {
                    Slog.w(TAG, "Couldn't delete native library directory " + libraryPath);
                }
            }

            return ret;
            return ret;
        }
        }


@@ -9779,31 +9877,26 @@ public class PackageManagerService extends IPackageManager.Stub {
                                    final String newNativePath = mp.targetArgs
                                    final String newNativePath = mp.targetArgs
                                            .getNativeLibraryPath();
                                            .getNativeLibraryPath();


                                    try {
                                    final File newNativeDir = new File(newNativePath);
                                    final File newNativeDir = new File(newNativePath);


                                        final String libParentDir = newNativeDir.getParentFile()
                                    if (!isForwardLocked(pkg) && !isExternal(pkg)) {
                                                .getCanonicalPath();
                                        synchronized (mInstallLock) {
                                        if (newNativeDir.getParentFile().getCanonicalPath()
                                            if (mInstaller.linkNativeLibraryDirectory(
                                                .equals(pkg.applicationInfo.dataDir)) {
                                                    pkg.applicationInfo.dataDir, newNativePath) < 0) {
                                            if (mInstaller
                                                    .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
                                            } else {
                                                NativeLibraryHelper.copyNativeBinariesIfNeededLI(
                                                        new File(newCodePath), newNativeDir);
                                            }
                                            }
                                        }
                                        NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File(
                                                newCodePath), newNativeDir);
                                    } else {
                                    } else {
                                        synchronized (mInstallLock) {
                                            if (mInstaller.linkNativeLibraryDirectory(
                                            if (mInstaller.linkNativeLibraryDirectory(
                                                    pkg.applicationInfo.dataDir, newNativePath) < 0) {
                                                    pkg.applicationInfo.dataDir, newNativePath) < 0) {
                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
                                            }
                                            }
                                        }
                                        }
                                    } catch (IOException e) {
                                        returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
                                    }
                                    }



                                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
                                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
                                        pkg.mPath = newCodePath;
                                        pkg.mPath = newCodePath;
                                        // Move dex files around
                                        // Move dex files around