Loading core/java/android/content/pm/IPackageInstallerSession.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ interface IPackageInstallerSession { ParcelFileDescriptor openRead(String name); void write(String name, long offsetBytes, long lengthBytes, in ParcelFileDescriptor fd); void stageViaHardLink(String target); void addChecksums(String name, in Checksum[] checksums); Loading core/java/android/content/pm/PackageInstaller.java +25 −0 Original line number Diff line number Diff line Loading @@ -1048,6 +1048,31 @@ public class PackageInstaller { } } /** * Populate an APK file by creating a hard link to avoid the need to copy. * <p> * Note this API is used by RollbackManager only and can only be called from system_server. * {@code target} will be relabeled if link is created successfully. RollbackManager has * to delete {@code target} when the session is committed successfully to avoid SELinux * label conflicts. * <p> * Note No more bytes should be written to the file once the link is created successfully. * * @param target the path of the link target * * @hide */ public void stageViaHardLink(String target) throws IOException { try { mSession.stageViaHardLink(target); } catch (RuntimeException e) { ExceptionUtils.maybeUnwrapIOException(e); throw e; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Ensure that any outstanding data for given stream has been committed * to disk. This is only valid for streams returned from Loading services/core/java/com/android/server/pm/PackageInstallerSession.java +26 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,7 @@ import android.os.ParcelableException; import android.os.Process; import android.os.RemoteException; import android.os.RevocableFileDescriptor; import android.os.SELinux; import android.os.SystemProperties; import android.os.UserHandle; import android.os.incremental.IStorageHealthListener; Loading Loading @@ -1088,6 +1089,31 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } @Override public void stageViaHardLink(String path) { final int callingUid = Binder.getCallingUid(); if (callingUid != Process.SYSTEM_UID) { throw new SecurityException("link() can only be run by the system"); } try { final File target = new File(path); final File source = new File(stageDir, target.getName()); try { Os.link(path, source.getAbsolutePath()); // Grant READ access for APK to be read successfully Os.chmod(source.getAbsolutePath(), 0644); } catch (ErrnoException e) { e.rethrowAsIOException(); } if (!SELinux.restorecon(source)) { throw new IOException("Can't relabel file: " + source); } } catch (IOException e) { throw ExceptionUtils.wrap(e); } } private ParcelFileDescriptor openTargetInternal(String path, int flags, int mode) throws IOException, ErrnoException { // TODO: this should delegate to DCS so the system process avoids Loading services/core/java/com/android/server/rollback/Rollback.java +12 −3 Original line number Diff line number Diff line Loading @@ -581,9 +581,18 @@ class Rollback { ParcelFileDescriptor.MODE_READ_ONLY)) { final long token = Binder.clearCallingIdentity(); try { boolean fallbackToCopy = false; try { // Populate apk/apex files using hard links to avoid copy session.stageViaHardLink(packageCodePath.getAbsolutePath()); } catch (Exception ignore) { fallbackToCopy = true; } if (fallbackToCopy) { session.write(packageCodePath.getName(), 0, packageCodePath.length(), fd); } } finally { Binder.restoreCallingIdentity(token); } Loading Loading
core/java/android/content/pm/IPackageInstallerSession.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ interface IPackageInstallerSession { ParcelFileDescriptor openRead(String name); void write(String name, long offsetBytes, long lengthBytes, in ParcelFileDescriptor fd); void stageViaHardLink(String target); void addChecksums(String name, in Checksum[] checksums); Loading
core/java/android/content/pm/PackageInstaller.java +25 −0 Original line number Diff line number Diff line Loading @@ -1048,6 +1048,31 @@ public class PackageInstaller { } } /** * Populate an APK file by creating a hard link to avoid the need to copy. * <p> * Note this API is used by RollbackManager only and can only be called from system_server. * {@code target} will be relabeled if link is created successfully. RollbackManager has * to delete {@code target} when the session is committed successfully to avoid SELinux * label conflicts. * <p> * Note No more bytes should be written to the file once the link is created successfully. * * @param target the path of the link target * * @hide */ public void stageViaHardLink(String target) throws IOException { try { mSession.stageViaHardLink(target); } catch (RuntimeException e) { ExceptionUtils.maybeUnwrapIOException(e); throw e; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Ensure that any outstanding data for given stream has been committed * to disk. This is only valid for streams returned from Loading
services/core/java/com/android/server/pm/PackageInstallerSession.java +26 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,7 @@ import android.os.ParcelableException; import android.os.Process; import android.os.RemoteException; import android.os.RevocableFileDescriptor; import android.os.SELinux; import android.os.SystemProperties; import android.os.UserHandle; import android.os.incremental.IStorageHealthListener; Loading Loading @@ -1088,6 +1089,31 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } @Override public void stageViaHardLink(String path) { final int callingUid = Binder.getCallingUid(); if (callingUid != Process.SYSTEM_UID) { throw new SecurityException("link() can only be run by the system"); } try { final File target = new File(path); final File source = new File(stageDir, target.getName()); try { Os.link(path, source.getAbsolutePath()); // Grant READ access for APK to be read successfully Os.chmod(source.getAbsolutePath(), 0644); } catch (ErrnoException e) { e.rethrowAsIOException(); } if (!SELinux.restorecon(source)) { throw new IOException("Can't relabel file: " + source); } } catch (IOException e) { throw ExceptionUtils.wrap(e); } } private ParcelFileDescriptor openTargetInternal(String path, int flags, int mode) throws IOException, ErrnoException { // TODO: this should delegate to DCS so the system process avoids Loading
services/core/java/com/android/server/rollback/Rollback.java +12 −3 Original line number Diff line number Diff line Loading @@ -581,9 +581,18 @@ class Rollback { ParcelFileDescriptor.MODE_READ_ONLY)) { final long token = Binder.clearCallingIdentity(); try { boolean fallbackToCopy = false; try { // Populate apk/apex files using hard links to avoid copy session.stageViaHardLink(packageCodePath.getAbsolutePath()); } catch (Exception ignore) { fallbackToCopy = true; } if (fallbackToCopy) { session.write(packageCodePath.getName(), 0, packageCodePath.length(), fd); } } finally { Binder.restoreCallingIdentity(token); } Loading