Loading core/java/android/os/incremental/IIncrementalService.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -103,4 +103,9 @@ interface IIncrementalService { * Deletes a storage given its ID. Deletes its bind mounts and unmount it. Stop its data loader. */ void deleteStorage(int storageId); /** * Setting up native library directories and extract native libs onto a storage. */ boolean configureNativeBinaries(int storageId, in @utf8InCpp String apkFullPath, in @utf8InCpp String libDirRelativePath, in @utf8InCpp String abi); } core/java/android/os/incremental/IncrementalManager.java +33 −8 Original line number Diff line number Diff line Loading @@ -229,16 +229,41 @@ public final class IncrementalManager { if (linkedApkStorage == null) { throw new IOException("Failed to create linked storage at dir: " + afterCodePathParent); } linkedApkStorage.makeDirectory(afterCodePathName); File[] files = beforeCodeFile.listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].isFile()) { String fileName = files[i].getName(); apkStorage.makeLink( fileName, linkedApkStorage, afterCodePathName + "/" + fileName); linkFiles(apkStorage, beforeCodeFile, "", linkedApkStorage, afterCodePathName); apkStorage.unBind(beforeCodePath); } /** * Recursively set up directories and link all the files from source storage to target storage. * * @param sourceStorage The storage that has all the files and directories underneath. * @param sourceAbsolutePath The absolute path of the directory that holds all files and dirs. * @param sourceRelativePath The relative path on the source directory, e.g., "" or "lib". * @param targetStorage The target storage that will have the same files and directories. * @param targetRelativePath The relative path to the directory on the target storage that * should have all the files and dirs underneath, * e.g., "packageName-random". * @throws IOException When makeDirectory or makeLink fails on the Incremental File System. */ private void linkFiles(IncrementalStorage sourceStorage, File sourceAbsolutePath, String sourceRelativePath, IncrementalStorage targetStorage, String targetRelativePath) throws IOException { targetStorage.makeDirectory(targetRelativePath); final File[] entryList = sourceAbsolutePath.listFiles(); for (int i = 0; i < entryList.length; i++) { final File entry = entryList[i]; final String entryName = entryList[i].getName(); final String sourceEntryRelativePath = sourceRelativePath.isEmpty() ? entryName : sourceRelativePath + "/" + entryName; final String targetEntryRelativePath = targetRelativePath + "/" + entryName; if (entry.isFile()) { sourceStorage.makeLink( sourceEntryRelativePath, targetStorage, targetEntryRelativePath); } else if (entry.isDirectory()) { linkFiles(sourceStorage, entry, sourceEntryRelativePath, targetStorage, targetEntryRelativePath); } } apkStorage.unBind(beforeCodePath); } /** Loading core/java/android/os/incremental/IncrementalStorage.java +20 −0 Original line number Diff line number Diff line Loading @@ -416,4 +416,24 @@ public final class IncrementalStorage { return false; } } /** * Configure all the lib files inside Incremental Service, e.g., create lib dirs, create new lib * files, extract original lib file data from zip and then write data to the lib files on the * Incremental File System. * * @param apkFullPath Source APK to extract native libs from. * @param libDirRelativePath Target dir to put lib files, e.g., "lib" or "lib/arm". * @param abi Target ABI of the native lib files. Only extract native libs of this ABI. * @return Success of not. */ public boolean configureNativeBinaries(String apkFullPath, String libDirRelativePath, String abi) { try { return mService.configureNativeBinaries(mId, apkFullPath, libDirRelativePath, abi); } catch (RemoteException e) { e.rethrowFromSystemServer(); return false; } } } core/java/com/android/internal/content/NativeLibraryHelper.java +55 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.system.OsConstants.S_IRWXU; import static android.system.OsConstants.S_IXGRP; import static android.system.OsConstants.S_IXOTH; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; Loading @@ -32,7 +33,12 @@ import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.parsing.AndroidPackage; import android.os.Build; import android.os.IBinder; import android.os.SELinux; import android.os.ServiceManager; import android.os.incremental.IIncrementalService; import android.os.incremental.IncrementalManager; import android.os.incremental.IncrementalStorage; import android.system.ErrnoException; import android.system.Os; import android.util.Slog; Loading @@ -44,6 +50,7 @@ import java.io.Closeable; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.nio.file.Path; import java.util.List; /** Loading Loading @@ -481,10 +488,56 @@ public class NativeLibraryHelper { */ private static int incrementalConfigureNativeBinariesForSupportedAbi(Handle handle, File libSubDir, String abi) { // TODO(b/136132412): implement this final String[] apkPaths = handle.apkPaths; if (apkPaths == null || apkPaths.length == 0) { Slog.e(TAG, "No apks to extract native libraries from."); return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } final IBinder incrementalService = ServiceManager.getService(Context.INCREMENTAL_SERVICE); if (incrementalService == null) { //TODO(b/133435829): add incremental specific error codes return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } final IncrementalManager incrementalManager = new IncrementalManager( IIncrementalService.Stub.asInterface(incrementalService)); final File apkParent = new File(apkPaths[0]).getParentFile(); IncrementalStorage incrementalStorage = incrementalManager.openStorage(apkParent.getAbsolutePath()); if (incrementalStorage == null) { Slog.e(TAG, "Failed to find incremental storage"); return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } String libRelativeDir = getRelativePath(apkParent, libSubDir); if (libRelativeDir == null) { return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } for (int i = 0; i < apkPaths.length; i++) { if (!incrementalStorage.configureNativeBinaries(apkPaths[i], libRelativeDir, abi)) { return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } } return PackageManager.INSTALL_SUCCEEDED; } private static String getRelativePath(File base, File target) { try { final Path basePath = base.toPath(); final Path targetPath = target.toPath(); final Path relativePath = basePath.relativize(targetPath); if (relativePath.toString().isEmpty()) { return ""; } return relativePath.toString(); } catch (IllegalArgumentException ex) { Slog.e(TAG, "Failed to find relative path between: " + base.getAbsolutePath() + " and: " + target.getAbsolutePath()); return null; } } // We don't care about the other return values for now. private static final int BITCODE_PRESENT = 1; Loading services/incremental/BinderIncrementalService.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "BinderIncrementalService.h" #include <android-base/logging.h> #include <binder/IResultReceiver.h> #include <binder/PermissionCache.h> #include <incfs.h> Loading @@ -24,7 +25,6 @@ #include "jni.h" #include "nativehelper/JNIHelp.h" #include "path.h" #include <android-base/logging.h> using namespace std::literals; using namespace android::incremental; Loading Loading @@ -277,6 +277,13 @@ binder::Status BinderIncrementalService::startLoading(int32_t storageId, bool* _ return ok(); } binder::Status BinderIncrementalService::configureNativeBinaries( int32_t storageId, const std::string& apkFullPath, const std::string& libDirRelativePath, const std::string& abi, bool* _aidl_return) { *_aidl_return = mImpl.configureNativeBinaries(storageId, apkFullPath, libDirRelativePath, abi); return ok(); } } // namespace android::os::incremental jlong Incremental_IncrementalService_Start() { Loading Loading
core/java/android/os/incremental/IIncrementalService.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -103,4 +103,9 @@ interface IIncrementalService { * Deletes a storage given its ID. Deletes its bind mounts and unmount it. Stop its data loader. */ void deleteStorage(int storageId); /** * Setting up native library directories and extract native libs onto a storage. */ boolean configureNativeBinaries(int storageId, in @utf8InCpp String apkFullPath, in @utf8InCpp String libDirRelativePath, in @utf8InCpp String abi); }
core/java/android/os/incremental/IncrementalManager.java +33 −8 Original line number Diff line number Diff line Loading @@ -229,16 +229,41 @@ public final class IncrementalManager { if (linkedApkStorage == null) { throw new IOException("Failed to create linked storage at dir: " + afterCodePathParent); } linkedApkStorage.makeDirectory(afterCodePathName); File[] files = beforeCodeFile.listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].isFile()) { String fileName = files[i].getName(); apkStorage.makeLink( fileName, linkedApkStorage, afterCodePathName + "/" + fileName); linkFiles(apkStorage, beforeCodeFile, "", linkedApkStorage, afterCodePathName); apkStorage.unBind(beforeCodePath); } /** * Recursively set up directories and link all the files from source storage to target storage. * * @param sourceStorage The storage that has all the files and directories underneath. * @param sourceAbsolutePath The absolute path of the directory that holds all files and dirs. * @param sourceRelativePath The relative path on the source directory, e.g., "" or "lib". * @param targetStorage The target storage that will have the same files and directories. * @param targetRelativePath The relative path to the directory on the target storage that * should have all the files and dirs underneath, * e.g., "packageName-random". * @throws IOException When makeDirectory or makeLink fails on the Incremental File System. */ private void linkFiles(IncrementalStorage sourceStorage, File sourceAbsolutePath, String sourceRelativePath, IncrementalStorage targetStorage, String targetRelativePath) throws IOException { targetStorage.makeDirectory(targetRelativePath); final File[] entryList = sourceAbsolutePath.listFiles(); for (int i = 0; i < entryList.length; i++) { final File entry = entryList[i]; final String entryName = entryList[i].getName(); final String sourceEntryRelativePath = sourceRelativePath.isEmpty() ? entryName : sourceRelativePath + "/" + entryName; final String targetEntryRelativePath = targetRelativePath + "/" + entryName; if (entry.isFile()) { sourceStorage.makeLink( sourceEntryRelativePath, targetStorage, targetEntryRelativePath); } else if (entry.isDirectory()) { linkFiles(sourceStorage, entry, sourceEntryRelativePath, targetStorage, targetEntryRelativePath); } } apkStorage.unBind(beforeCodePath); } /** Loading
core/java/android/os/incremental/IncrementalStorage.java +20 −0 Original line number Diff line number Diff line Loading @@ -416,4 +416,24 @@ public final class IncrementalStorage { return false; } } /** * Configure all the lib files inside Incremental Service, e.g., create lib dirs, create new lib * files, extract original lib file data from zip and then write data to the lib files on the * Incremental File System. * * @param apkFullPath Source APK to extract native libs from. * @param libDirRelativePath Target dir to put lib files, e.g., "lib" or "lib/arm". * @param abi Target ABI of the native lib files. Only extract native libs of this ABI. * @return Success of not. */ public boolean configureNativeBinaries(String apkFullPath, String libDirRelativePath, String abi) { try { return mService.configureNativeBinaries(mId, apkFullPath, libDirRelativePath, abi); } catch (RemoteException e) { e.rethrowFromSystemServer(); return false; } } }
core/java/com/android/internal/content/NativeLibraryHelper.java +55 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.system.OsConstants.S_IRWXU; import static android.system.OsConstants.S_IXGRP; import static android.system.OsConstants.S_IXOTH; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; Loading @@ -32,7 +33,12 @@ import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.parsing.AndroidPackage; import android.os.Build; import android.os.IBinder; import android.os.SELinux; import android.os.ServiceManager; import android.os.incremental.IIncrementalService; import android.os.incremental.IncrementalManager; import android.os.incremental.IncrementalStorage; import android.system.ErrnoException; import android.system.Os; import android.util.Slog; Loading @@ -44,6 +50,7 @@ import java.io.Closeable; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.nio.file.Path; import java.util.List; /** Loading Loading @@ -481,10 +488,56 @@ public class NativeLibraryHelper { */ private static int incrementalConfigureNativeBinariesForSupportedAbi(Handle handle, File libSubDir, String abi) { // TODO(b/136132412): implement this final String[] apkPaths = handle.apkPaths; if (apkPaths == null || apkPaths.length == 0) { Slog.e(TAG, "No apks to extract native libraries from."); return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } final IBinder incrementalService = ServiceManager.getService(Context.INCREMENTAL_SERVICE); if (incrementalService == null) { //TODO(b/133435829): add incremental specific error codes return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } final IncrementalManager incrementalManager = new IncrementalManager( IIncrementalService.Stub.asInterface(incrementalService)); final File apkParent = new File(apkPaths[0]).getParentFile(); IncrementalStorage incrementalStorage = incrementalManager.openStorage(apkParent.getAbsolutePath()); if (incrementalStorage == null) { Slog.e(TAG, "Failed to find incremental storage"); return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } String libRelativeDir = getRelativePath(apkParent, libSubDir); if (libRelativeDir == null) { return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } for (int i = 0; i < apkPaths.length; i++) { if (!incrementalStorage.configureNativeBinaries(apkPaths[i], libRelativeDir, abi)) { return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } } return PackageManager.INSTALL_SUCCEEDED; } private static String getRelativePath(File base, File target) { try { final Path basePath = base.toPath(); final Path targetPath = target.toPath(); final Path relativePath = basePath.relativize(targetPath); if (relativePath.toString().isEmpty()) { return ""; } return relativePath.toString(); } catch (IllegalArgumentException ex) { Slog.e(TAG, "Failed to find relative path between: " + base.getAbsolutePath() + " and: " + target.getAbsolutePath()); return null; } } // We don't care about the other return values for now. private static final int BITCODE_PRESENT = 1; Loading
services/incremental/BinderIncrementalService.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "BinderIncrementalService.h" #include <android-base/logging.h> #include <binder/IResultReceiver.h> #include <binder/PermissionCache.h> #include <incfs.h> Loading @@ -24,7 +25,6 @@ #include "jni.h" #include "nativehelper/JNIHelp.h" #include "path.h" #include <android-base/logging.h> using namespace std::literals; using namespace android::incremental; Loading Loading @@ -277,6 +277,13 @@ binder::Status BinderIncrementalService::startLoading(int32_t storageId, bool* _ return ok(); } binder::Status BinderIncrementalService::configureNativeBinaries( int32_t storageId, const std::string& apkFullPath, const std::string& libDirRelativePath, const std::string& abi, bool* _aidl_return) { *_aidl_return = mImpl.configureNativeBinaries(storageId, apkFullPath, libDirRelativePath, abi); return ok(); } } // namespace android::os::incremental jlong Incremental_IncrementalService_Start() { Loading