Loading api/system-current.txt +5 −8 Original line number Diff line number Diff line Loading @@ -2007,18 +2007,15 @@ package android.content.pm { } public final class InstallationFile implements android.os.Parcelable { ctor public InstallationFile(@NonNull String, long, @Nullable byte[]); ctor public InstallationFile(int, @NonNull String, long, @Nullable byte[], @Nullable byte[]); method public int describeContents(); method public int getFileType(); method public long getLengthBytes(); method public int getLocation(); method @Nullable public byte[] getMetadata(); method @NonNull public String getName(); method public long getSize(); method @Nullable public byte[] getSignature(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.InstallationFile> CREATOR; field public static final int FILE_TYPE_APK = 0; // 0x0 field public static final int FILE_TYPE_LIB = 1; // 0x1 field public static final int FILE_TYPE_OBB = 2; // 0x2 field public static final int FILE_TYPE_UNKNOWN = -1; // 0xffffffff } public final class InstantAppInfo implements android.os.Parcelable { Loading Loading @@ -10317,7 +10314,7 @@ package android.service.dataloader { public abstract class DataLoaderService extends android.app.Service { ctor public DataLoaderService(); method @Nullable public android.service.dataloader.DataLoaderService.DataLoader onCreateDataLoader(); method @Nullable public android.service.dataloader.DataLoaderService.DataLoader onCreateDataLoader(@NonNull android.content.pm.DataLoaderParams); } public static interface DataLoaderService.DataLoader { core/java/android/content/pm/InstallationFile.java +29 −51 Original line number Diff line number Diff line Loading @@ -16,82 +16,59 @@ package android.content.pm; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Defines the properties of a file in an installation session. * TODO(b/136132412): update with new APIs. * * @hide */ @SystemApi public final class InstallationFile implements Parcelable { public static final int FILE_TYPE_UNKNOWN = -1; public static final int FILE_TYPE_APK = 0; public static final int FILE_TYPE_LIB = 1; public static final int FILE_TYPE_OBB = 2; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"FILE_TYPE_"}, value = { FILE_TYPE_APK, FILE_TYPE_LIB, FILE_TYPE_OBB, }) public @interface FileType { } private String mFileName; private @FileType int mFileType; private long mFileSize; private byte[] mMetadata; public InstallationFile(@NonNull String fileName, long fileSize, @Nullable byte[] metadata) { mFileName = fileName; mFileSize = fileSize; private final @PackageInstaller.FileLocation int mLocation; private final @NonNull String mName; private final long mLengthBytes; private final @Nullable byte[] mMetadata; private final @Nullable byte[] mSignature; public InstallationFile(@PackageInstaller.FileLocation int location, @NonNull String name, long lengthBytes, @Nullable byte[] metadata, @Nullable byte[] signature) { mLocation = location; mName = name; mLengthBytes = lengthBytes; mMetadata = metadata; if (fileName.toLowerCase().endsWith(".apk")) { mFileType = FILE_TYPE_APK; } else if (fileName.toLowerCase().endsWith(".obb")) { mFileType = FILE_TYPE_OBB; } else if (fileName.toLowerCase().endsWith(".so") && fileName.toLowerCase().startsWith( "lib/")) { mFileType = FILE_TYPE_LIB; } else { mFileType = FILE_TYPE_UNKNOWN; } mSignature = signature; } public @FileType int getFileType() { return mFileType; public @PackageInstaller.FileLocation int getLocation() { return mLocation; } public @NonNull String getName() { return mFileName; return mName; } public long getSize() { return mFileSize; public long getLengthBytes() { return mLengthBytes; } public @Nullable byte[] getMetadata() { return mMetadata; } public @Nullable byte[] getSignature() { return mSignature; } private InstallationFile(Parcel source) { mFileName = source.readString(); mFileType = source.readInt(); mFileSize = source.readLong(); mLocation = source.readInt(); mName = source.readString(); mLengthBytes = source.readLong(); mMetadata = source.createByteArray(); mSignature = source.createByteArray(); } @Override Loading @@ -101,10 +78,11 @@ public final class InstallationFile implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mFileName); dest.writeInt(mFileType); dest.writeLong(mFileSize); dest.writeInt(mLocation); dest.writeString(mName); dest.writeLong(mLengthBytes); dest.writeByteArray(mMetadata); dest.writeByteArray(mSignature); } public static final @NonNull Creator<InstallationFile> CREATOR = Loading core/java/android/os/incremental/IncrementalFileStorages.java +6 −4 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ package android.os.incremental; * @throws IllegalStateException the session is not an Incremental installation session. */ import static android.content.pm.PackageInstaller.LOCATION_DATA_APP; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; Loading Loading @@ -85,7 +87,7 @@ public final class IncrementalFileStorages { try { result = new IncrementalFileStorages(stageDir, incrementalManager, dataLoaderParams); for (InstallationFile file : addedFiles) { if (file.getFileType() == InstallationFile.FILE_TYPE_APK) { if (file.getLocation() == LOCATION_DATA_APP) { try { result.addApkFile(file); } catch (IOException e) { Loading @@ -95,7 +97,7 @@ public final class IncrementalFileStorages { e); } } else { throw new IOException("Unknown file type: " + file.getFileType()); throw new IOException("Unknown file location: " + file.getLocation()); } } Loading Loading @@ -147,8 +149,8 @@ public final class IncrementalFileStorages { String apkName = apk.getName(); File targetFile = Paths.get(stageDirPath, apkName).toFile(); if (!targetFile.exists()) { mDefaultStorage.makeFile(apkName, apk.getSize(), null, apk.getMetadata(), 0, null, null, null); mDefaultStorage.makeFile(apkName, apk.getLengthBytes(), null, apk.getMetadata(), apk.getSignature()); } } Loading core/java/android/os/incremental/IncrementalManager.java +9 −0 Original line number Diff line number Diff line Loading @@ -299,7 +299,16 @@ public final class IncrementalManager { return nativeIsIncrementalPath(path); } /** * Returns raw signature for file if it's on Incremental File System. * Unsafe, use only if you are sure what you are doing. */ public static @Nullable byte[] unsafeGetFileSignature(@NonNull String path) { return nativeUnsafeGetFileSignature(path); } /* Native methods */ private static native boolean nativeIsEnabled(); private static native boolean nativeIsIncrementalPath(@NonNull String path); private static native byte[] nativeUnsafeGetFileSignature(@NonNull String path); } core/java/android/os/incremental/IncrementalStorage.java +70 −32 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.RemoteException; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; Loading Loading @@ -169,10 +171,11 @@ public final class IncrementalStorage { * @param path Relative path of the new file. * @param size Size of the new file in bytes. * @param metadata Metadata bytes. * @param v4signatureBytes Serialized V4SignatureProto. */ public void makeFile(@NonNull String path, long size, @Nullable UUID id, @Nullable byte[] metadata, int hashAlgorithm, @Nullable byte[] rootHash, @Nullable byte[] additionalData, @Nullable byte[] signature) throws IOException { @Nullable byte[] metadata, @Nullable byte[] v4signatureBytes) throws IOException { try { if (id == null && metadata == null) { throw new IOException("File ID and metadata cannot both be null"); Loading @@ -181,13 +184,7 @@ public final class IncrementalStorage { params.size = size; params.metadata = (metadata == null ? new byte[0] : metadata); params.fileId = idToBytes(id); if (hashAlgorithm != 0 || signature != null) { params.signature = new IncrementalSignature(); params.signature.hashAlgorithm = hashAlgorithm; params.signature.rootHash = rootHash; params.signature.additionalData = additionalData; params.signature.signature = signature; } params.signature = parseV4Signature(v4signatureBytes); int res = mService.makeFile(mId, path, params); if (res != 0) { throw new IOException("makeFile() failed with errno " + -res); Loading @@ -197,6 +194,7 @@ public final class IncrementalStorage { } } /** * Creates a file in Incremental storage. The content of the file is mapped from a range inside * a source file in the same storage. Loading Loading @@ -349,6 +347,37 @@ public final class IncrementalStorage { } } /** * Returns the metadata object of an IncFs File. * * @param id The file id. * @return Byte array that contains metadata bytes. */ @Nullable public byte[] getFileMetadata(@NonNull UUID id) { try { final byte[] rawId = idToBytes(id); return mService.getMetadataById(mId, rawId); } catch (RemoteException e) { e.rethrowFromSystemServer(); return null; } } /** * Informs the data loader service associated with the current storage to start data loader * * @return True if data loader is successfully started. */ public boolean startLoading() { try { return mService.startLoading(mId); } catch (RemoteException e) { e.rethrowFromSystemServer(); return false; } } private static final int UUID_BYTE_SIZE = 16; /** Loading Loading @@ -386,35 +415,44 @@ public final class IncrementalStorage { return new UUID(msb, lsb); } private static final int INCFS_HASH_SHA256 = 1; private static final int INCFS_MAX_HASH_SIZE = 32; // SHA256 private static final int INCFS_MAX_ADD_DATA_SIZE = 128; /** * Returns the metadata object of an IncFs File. * * @param id The file id. * @return Byte array that contains metadata bytes. * Deserialize and validate v4 signature bytes. */ @Nullable public byte[] getFileMetadata(@NonNull UUID id) { try { final byte[] rawId = idToBytes(id); return mService.getMetadataById(mId, rawId); } catch (RemoteException e) { e.rethrowFromSystemServer(); private static IncrementalSignature parseV4Signature(@Nullable byte[] v4signatureBytes) throws IOException { if (v4signatureBytes == null) { return null; } final V4Signature signature; try (DataInputStream input = new DataInputStream( new ByteArrayInputStream(v4signatureBytes))) { signature = V4Signature.readFrom(input); } /** * Informs the data loader service associated with the current storage to start data loader * * @return True if data loader is successfully started. */ public boolean startLoading() { try { return mService.startLoading(mId); } catch (RemoteException e) { e.rethrowFromSystemServer(); return false; final byte[] rootHash = signature.verityRootHash; final byte[] additionalData = signature.v3Digest; final byte[] pkcs7Signature = signature.pkcs7SignatureBlock; if (rootHash.length != INCFS_MAX_HASH_SIZE) { throw new IOException("rootHash has to be " + INCFS_MAX_HASH_SIZE + " bytes"); } if (additionalData.length > INCFS_MAX_ADD_DATA_SIZE) { throw new IOException( "additionalData has to be at most " + INCFS_MAX_ADD_DATA_SIZE + " bytes"); } IncrementalSignature result = new IncrementalSignature(); result.hashAlgorithm = INCFS_HASH_SHA256; result.rootHash = rootHash; result.additionalData = additionalData; result.signature = pkcs7Signature; return result; } /** Loading Loading
api/system-current.txt +5 −8 Original line number Diff line number Diff line Loading @@ -2007,18 +2007,15 @@ package android.content.pm { } public final class InstallationFile implements android.os.Parcelable { ctor public InstallationFile(@NonNull String, long, @Nullable byte[]); ctor public InstallationFile(int, @NonNull String, long, @Nullable byte[], @Nullable byte[]); method public int describeContents(); method public int getFileType(); method public long getLengthBytes(); method public int getLocation(); method @Nullable public byte[] getMetadata(); method @NonNull public String getName(); method public long getSize(); method @Nullable public byte[] getSignature(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.InstallationFile> CREATOR; field public static final int FILE_TYPE_APK = 0; // 0x0 field public static final int FILE_TYPE_LIB = 1; // 0x1 field public static final int FILE_TYPE_OBB = 2; // 0x2 field public static final int FILE_TYPE_UNKNOWN = -1; // 0xffffffff } public final class InstantAppInfo implements android.os.Parcelable { Loading Loading @@ -10317,7 +10314,7 @@ package android.service.dataloader { public abstract class DataLoaderService extends android.app.Service { ctor public DataLoaderService(); method @Nullable public android.service.dataloader.DataLoaderService.DataLoader onCreateDataLoader(); method @Nullable public android.service.dataloader.DataLoaderService.DataLoader onCreateDataLoader(@NonNull android.content.pm.DataLoaderParams); } public static interface DataLoaderService.DataLoader {
core/java/android/content/pm/InstallationFile.java +29 −51 Original line number Diff line number Diff line Loading @@ -16,82 +16,59 @@ package android.content.pm; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Defines the properties of a file in an installation session. * TODO(b/136132412): update with new APIs. * * @hide */ @SystemApi public final class InstallationFile implements Parcelable { public static final int FILE_TYPE_UNKNOWN = -1; public static final int FILE_TYPE_APK = 0; public static final int FILE_TYPE_LIB = 1; public static final int FILE_TYPE_OBB = 2; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"FILE_TYPE_"}, value = { FILE_TYPE_APK, FILE_TYPE_LIB, FILE_TYPE_OBB, }) public @interface FileType { } private String mFileName; private @FileType int mFileType; private long mFileSize; private byte[] mMetadata; public InstallationFile(@NonNull String fileName, long fileSize, @Nullable byte[] metadata) { mFileName = fileName; mFileSize = fileSize; private final @PackageInstaller.FileLocation int mLocation; private final @NonNull String mName; private final long mLengthBytes; private final @Nullable byte[] mMetadata; private final @Nullable byte[] mSignature; public InstallationFile(@PackageInstaller.FileLocation int location, @NonNull String name, long lengthBytes, @Nullable byte[] metadata, @Nullable byte[] signature) { mLocation = location; mName = name; mLengthBytes = lengthBytes; mMetadata = metadata; if (fileName.toLowerCase().endsWith(".apk")) { mFileType = FILE_TYPE_APK; } else if (fileName.toLowerCase().endsWith(".obb")) { mFileType = FILE_TYPE_OBB; } else if (fileName.toLowerCase().endsWith(".so") && fileName.toLowerCase().startsWith( "lib/")) { mFileType = FILE_TYPE_LIB; } else { mFileType = FILE_TYPE_UNKNOWN; } mSignature = signature; } public @FileType int getFileType() { return mFileType; public @PackageInstaller.FileLocation int getLocation() { return mLocation; } public @NonNull String getName() { return mFileName; return mName; } public long getSize() { return mFileSize; public long getLengthBytes() { return mLengthBytes; } public @Nullable byte[] getMetadata() { return mMetadata; } public @Nullable byte[] getSignature() { return mSignature; } private InstallationFile(Parcel source) { mFileName = source.readString(); mFileType = source.readInt(); mFileSize = source.readLong(); mLocation = source.readInt(); mName = source.readString(); mLengthBytes = source.readLong(); mMetadata = source.createByteArray(); mSignature = source.createByteArray(); } @Override Loading @@ -101,10 +78,11 @@ public final class InstallationFile implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mFileName); dest.writeInt(mFileType); dest.writeLong(mFileSize); dest.writeInt(mLocation); dest.writeString(mName); dest.writeLong(mLengthBytes); dest.writeByteArray(mMetadata); dest.writeByteArray(mSignature); } public static final @NonNull Creator<InstallationFile> CREATOR = Loading
core/java/android/os/incremental/IncrementalFileStorages.java +6 −4 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ package android.os.incremental; * @throws IllegalStateException the session is not an Incremental installation session. */ import static android.content.pm.PackageInstaller.LOCATION_DATA_APP; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; Loading Loading @@ -85,7 +87,7 @@ public final class IncrementalFileStorages { try { result = new IncrementalFileStorages(stageDir, incrementalManager, dataLoaderParams); for (InstallationFile file : addedFiles) { if (file.getFileType() == InstallationFile.FILE_TYPE_APK) { if (file.getLocation() == LOCATION_DATA_APP) { try { result.addApkFile(file); } catch (IOException e) { Loading @@ -95,7 +97,7 @@ public final class IncrementalFileStorages { e); } } else { throw new IOException("Unknown file type: " + file.getFileType()); throw new IOException("Unknown file location: " + file.getLocation()); } } Loading Loading @@ -147,8 +149,8 @@ public final class IncrementalFileStorages { String apkName = apk.getName(); File targetFile = Paths.get(stageDirPath, apkName).toFile(); if (!targetFile.exists()) { mDefaultStorage.makeFile(apkName, apk.getSize(), null, apk.getMetadata(), 0, null, null, null); mDefaultStorage.makeFile(apkName, apk.getLengthBytes(), null, apk.getMetadata(), apk.getSignature()); } } Loading
core/java/android/os/incremental/IncrementalManager.java +9 −0 Original line number Diff line number Diff line Loading @@ -299,7 +299,16 @@ public final class IncrementalManager { return nativeIsIncrementalPath(path); } /** * Returns raw signature for file if it's on Incremental File System. * Unsafe, use only if you are sure what you are doing. */ public static @Nullable byte[] unsafeGetFileSignature(@NonNull String path) { return nativeUnsafeGetFileSignature(path); } /* Native methods */ private static native boolean nativeIsEnabled(); private static native boolean nativeIsIncrementalPath(@NonNull String path); private static native byte[] nativeUnsafeGetFileSignature(@NonNull String path); }
core/java/android/os/incremental/IncrementalStorage.java +70 −32 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.RemoteException; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; Loading Loading @@ -169,10 +171,11 @@ public final class IncrementalStorage { * @param path Relative path of the new file. * @param size Size of the new file in bytes. * @param metadata Metadata bytes. * @param v4signatureBytes Serialized V4SignatureProto. */ public void makeFile(@NonNull String path, long size, @Nullable UUID id, @Nullable byte[] metadata, int hashAlgorithm, @Nullable byte[] rootHash, @Nullable byte[] additionalData, @Nullable byte[] signature) throws IOException { @Nullable byte[] metadata, @Nullable byte[] v4signatureBytes) throws IOException { try { if (id == null && metadata == null) { throw new IOException("File ID and metadata cannot both be null"); Loading @@ -181,13 +184,7 @@ public final class IncrementalStorage { params.size = size; params.metadata = (metadata == null ? new byte[0] : metadata); params.fileId = idToBytes(id); if (hashAlgorithm != 0 || signature != null) { params.signature = new IncrementalSignature(); params.signature.hashAlgorithm = hashAlgorithm; params.signature.rootHash = rootHash; params.signature.additionalData = additionalData; params.signature.signature = signature; } params.signature = parseV4Signature(v4signatureBytes); int res = mService.makeFile(mId, path, params); if (res != 0) { throw new IOException("makeFile() failed with errno " + -res); Loading @@ -197,6 +194,7 @@ public final class IncrementalStorage { } } /** * Creates a file in Incremental storage. The content of the file is mapped from a range inside * a source file in the same storage. Loading Loading @@ -349,6 +347,37 @@ public final class IncrementalStorage { } } /** * Returns the metadata object of an IncFs File. * * @param id The file id. * @return Byte array that contains metadata bytes. */ @Nullable public byte[] getFileMetadata(@NonNull UUID id) { try { final byte[] rawId = idToBytes(id); return mService.getMetadataById(mId, rawId); } catch (RemoteException e) { e.rethrowFromSystemServer(); return null; } } /** * Informs the data loader service associated with the current storage to start data loader * * @return True if data loader is successfully started. */ public boolean startLoading() { try { return mService.startLoading(mId); } catch (RemoteException e) { e.rethrowFromSystemServer(); return false; } } private static final int UUID_BYTE_SIZE = 16; /** Loading Loading @@ -386,35 +415,44 @@ public final class IncrementalStorage { return new UUID(msb, lsb); } private static final int INCFS_HASH_SHA256 = 1; private static final int INCFS_MAX_HASH_SIZE = 32; // SHA256 private static final int INCFS_MAX_ADD_DATA_SIZE = 128; /** * Returns the metadata object of an IncFs File. * * @param id The file id. * @return Byte array that contains metadata bytes. * Deserialize and validate v4 signature bytes. */ @Nullable public byte[] getFileMetadata(@NonNull UUID id) { try { final byte[] rawId = idToBytes(id); return mService.getMetadataById(mId, rawId); } catch (RemoteException e) { e.rethrowFromSystemServer(); private static IncrementalSignature parseV4Signature(@Nullable byte[] v4signatureBytes) throws IOException { if (v4signatureBytes == null) { return null; } final V4Signature signature; try (DataInputStream input = new DataInputStream( new ByteArrayInputStream(v4signatureBytes))) { signature = V4Signature.readFrom(input); } /** * Informs the data loader service associated with the current storage to start data loader * * @return True if data loader is successfully started. */ public boolean startLoading() { try { return mService.startLoading(mId); } catch (RemoteException e) { e.rethrowFromSystemServer(); return false; final byte[] rootHash = signature.verityRootHash; final byte[] additionalData = signature.v3Digest; final byte[] pkcs7Signature = signature.pkcs7SignatureBlock; if (rootHash.length != INCFS_MAX_HASH_SIZE) { throw new IOException("rootHash has to be " + INCFS_MAX_HASH_SIZE + " bytes"); } if (additionalData.length > INCFS_MAX_ADD_DATA_SIZE) { throw new IOException( "additionalData has to be at most " + INCFS_MAX_ADD_DATA_SIZE + " bytes"); } IncrementalSignature result = new IncrementalSignature(); result.hashAlgorithm = INCFS_HASH_SHA256; result.rootHash = rootHash; result.additionalData = additionalData; result.signature = pkcs7Signature; return result; } /** Loading