Loading core/java/com/android/server/AppWidgetBackupBridge.java +4 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import android.annotation.Nullable; import java.util.List; /** Loading @@ -37,6 +39,8 @@ public class AppWidgetBackupBridge { : null; } /** Returns a byte array of widget data for the specified package or {@code null}. */ @Nullable public static byte[] getWidgetState(String packageName, int userId) { return (sAppWidgetService != null) ? sAppWidgetService.getWidgetState(packageName, userId) Loading services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java +12 −7 Original line number Diff line number Diff line Loading @@ -9,9 +9,9 @@ import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT import android.app.ApplicationThreadConstants; import android.app.IBackupAgent; import android.app.backup.IBackupCallback; import android.app.backup.FullBackup; import android.app.backup.FullBackupDataOutput; import android.app.backup.IBackupCallback; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -21,6 +21,7 @@ import android.os.SELinux; import android.util.Slog; import com.android.internal.util.Preconditions; import com.android.server.backup.fullbackup.AppMetadataBackupWriter; import com.android.server.backup.remote.ServiceBackupCallback; import com.android.server.backup.utils.FullBackupUtils; Loading Loading @@ -202,16 +203,20 @@ public class KeyValueAdbBackupEngine { public void run() { try { FullBackupDataOutput output = new FullBackupDataOutput(mPipe); AppMetadataBackupWriter writer = new AppMetadataBackupWriter(output, mPackageManager); if (DEBUG) { Slog.d(TAG, "Writing manifest for " + mPackage.packageName); } FullBackupUtils.writeAppManifest( mPackage, mPackageManager, mManifestFile, false, false); FullBackup.backupToTar(mPackage.packageName, FullBackup.KEY_VALUE_DATA_TOKEN, null, mDataDir.getAbsolutePath(), mManifestFile.getAbsolutePath(), output); writer.backupManifest( mPackage, mManifestFile, mDataDir, FullBackup.KEY_VALUE_DATA_TOKEN, /* linkDomain */ null, /* withApk */ false); mManifestFile.delete(); if (DEBUG) { Loading services/backup/java/com/android/server/backup/fullbackup/AppMetadataBackupWriter.java 0 → 100644 +283 −0 Original line number Diff line number Diff line package com.android.server.backup.fullbackup; import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_VERSION; import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_VERSION; import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN; import static com.android.server.backup.BackupManagerService.MORE_DEBUG; import static com.android.server.backup.BackupManagerService.TAG; import android.annotation.Nullable; import android.app.backup.FullBackup; import android.app.backup.FullBackupDataOutput; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.os.Build; import android.os.Environment; import android.os.UserHandle; import android.util.Log; import android.util.StringBuilderPrinter; import com.android.internal.util.Preconditions; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; /** * Writes the backup of app-specific metadata to {@link FullBackupDataOutput}. This data is not * backed up by the app's backup agent and is written before the agent writes its own data. This * includes the app's: * * <ul> * <li>manifest * <li>widget data * <li>apk * <li>obb content * </ul> */ // TODO(b/113807190): Fix or remove apk and obb implementation (only used for adb). public class AppMetadataBackupWriter { private final FullBackupDataOutput mOutput; private final PackageManager mPackageManager; /** The destination of the backup is specified by {@code output}. */ public AppMetadataBackupWriter(FullBackupDataOutput output, PackageManager packageManager) { mOutput = output; mPackageManager = packageManager; } /** * Back up the app's manifest without specifying a pseudo-directory for the TAR stream. * * @see #backupManifest(PackageInfo, File, File, String, String, boolean) */ public void backupManifest( PackageInfo packageInfo, File manifestFile, File filesDir, boolean withApk) throws IOException { backupManifest( packageInfo, manifestFile, filesDir, /* domain */ null, /* linkDomain */ null, withApk); } /** * Back up the app's manifest. * * <ol> * <li>Write the app's manifest data to the specified temporary file {@code manifestFile}. * <li>Backup the file in TAR format to the backup destination {@link #mOutput}. * </ol> * * <p>Note: {@code domain} and {@code linkDomain} are only used by adb to specify a * pseudo-directory for the TAR stream. */ // TODO(b/113806991): Look into streaming the backup data directly. public void backupManifest( PackageInfo packageInfo, File manifestFile, File filesDir, @Nullable String domain, @Nullable String linkDomain, boolean withApk) throws IOException { byte[] manifestBytes = getManifestBytes(packageInfo, withApk); FileOutputStream outputStream = new FileOutputStream(manifestFile); outputStream.write(manifestBytes); outputStream.close(); // We want the manifest block in the archive stream to be constant each time we generate // a backup stream for the app. However, the underlying TAR mechanism sees it as a file and // will propagate its last modified time. We pin the last modified time to zero to prevent // the TAR header from varying. manifestFile.setLastModified(0); FullBackup.backupToTar( packageInfo.packageName, domain, linkDomain, filesDir.getAbsolutePath(), manifestFile.getAbsolutePath(), mOutput); } /** * Gets the app's manifest as a byte array. All data are strings ending in LF. * * <p>The manifest format is: * * <pre> * BACKUP_MANIFEST_VERSION * package name * package version code * platform version code * installer package name (can be empty) * boolean (1 if archive includes .apk, otherwise 0) * # of signatures N * N* (signature byte array in ascii format per Signature.toCharsString()) * </pre> */ private byte[] getManifestBytes(PackageInfo packageInfo, boolean withApk) { String packageName = packageInfo.packageName; StringBuilder builder = new StringBuilder(4096); StringBuilderPrinter printer = new StringBuilderPrinter(builder); printer.println(Integer.toString(BACKUP_MANIFEST_VERSION)); printer.println(packageName); printer.println(Long.toString(packageInfo.getLongVersionCode())); printer.println(Integer.toString(Build.VERSION.SDK_INT)); String installerName = mPackageManager.getInstallerPackageName(packageName); printer.println((installerName != null) ? installerName : ""); printer.println(withApk ? "1" : "0"); // Write the signature block. SigningInfo signingInfo = packageInfo.signingInfo; if (signingInfo == null) { printer.println("0"); } else { // Retrieve the newest signatures to write. // TODO (b/73988180) use entire signing history in case of rollbacks. Signature[] signatures = signingInfo.getApkContentsSigners(); printer.println(Integer.toString(signatures.length)); for (Signature sig : signatures) { printer.println(sig.toCharsString()); } } return builder.toString().getBytes(); } /** * Backup specified widget data. The widget data is prefaced by a metadata header. * * <ol> * <li>Write a metadata header to the specified temporary file {@code metadataFile}. * <li>Write widget data bytes to the same file. * <li>Backup the file in TAR format to the backup destination {@link #mOutput}. * </ol> * * @throws IllegalArgumentException if the widget data provided is empty. */ // TODO(b/113806991): Look into streaming the backup data directly. public void backupWidget( PackageInfo packageInfo, File metadataFile, File filesDir, byte[] widgetData) throws IOException { Preconditions.checkArgument(widgetData.length > 0, "Can't backup widget with no data."); String packageName = packageInfo.packageName; FileOutputStream fileOutputStream = new FileOutputStream(metadataFile); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream); byte[] metadata = getMetadataBytes(packageName); bufferedOutputStream.write(metadata); // bypassing DataOutputStream writeWidgetData(dataOutputStream, widgetData); bufferedOutputStream.flush(); dataOutputStream.close(); // As with the manifest file, guarantee consistency of the archive metadata for the widget // block by using a fixed last modified time on the metadata file. metadataFile.setLastModified(0); FullBackup.backupToTar( packageName, /* domain */ null, /* linkDomain */ null, filesDir.getAbsolutePath(), metadataFile.getAbsolutePath(), mOutput); } /** * Gets the app's metadata as a byte array. All entries are strings ending in LF. * * <p>The metadata format is: * * <pre> * BACKUP_METADATA_VERSION * package name * </pre> */ private byte[] getMetadataBytes(String packageName) { StringBuilder builder = new StringBuilder(512); StringBuilderPrinter printer = new StringBuilderPrinter(builder); printer.println(Integer.toString(BACKUP_METADATA_VERSION)); printer.println(packageName); return builder.toString().getBytes(); } /** * Write a byte array of widget data to the specified output stream. All integers are binary in * network byte order. * * <p>The widget data format: * * <pre> * 4 : Integer token identifying the widget data blob. * 4 : Integer size of the widget data. * N : Raw bytes of the widget data. * </pre> */ private void writeWidgetData(DataOutputStream out, byte[] widgetData) throws IOException { out.writeInt(BACKUP_WIDGET_METADATA_TOKEN); out.writeInt(widgetData.length); out.write(widgetData); } /** * Backup the app's .apk to the backup destination {@link #mOutput}. Currently only used for * 'adb backup'. */ // TODO(b/113807190): Investigate and potentially remove. public void backupApk(PackageInfo packageInfo) { // TODO: handle backing up split APKs String appSourceDir = packageInfo.applicationInfo.getBaseCodePath(); String apkDir = new File(appSourceDir).getParent(); FullBackup.backupToTar( packageInfo.packageName, FullBackup.APK_TREE_TOKEN, /* linkDomain */ null, apkDir, appSourceDir, mOutput); } /** * Backup the app's .obb files to the backup destination {@link #mOutput}. Currently only used * for 'adb backup'. */ // TODO(b/113807190): Investigate and potentially remove. public void backupObb(PackageInfo packageInfo) { // TODO: migrate this to SharedStorageBackup, since AID_SYSTEM doesn't have access to // external storage. // TODO: http://b/22388012 Environment.UserEnvironment userEnv = new Environment.UserEnvironment(UserHandle.USER_SYSTEM); File obbDir = userEnv.buildExternalStorageAppObbDirs(packageInfo.packageName)[0]; if (obbDir != null) { if (MORE_DEBUG) { Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath()); } File[] obbFiles = obbDir.listFiles(); if (obbFiles != null) { String obbDirName = obbDir.getAbsolutePath(); for (File obb : obbFiles) { FullBackup.backupToTar( packageInfo.packageName, FullBackup.OBB_TREE_TOKEN, /* linkDomain */ null, obbDirName, obb.getAbsolutePath(), mOutput); } } } } } services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java +102 −168 File changed.Preview size limit exceeded, changes collapsed. Show changes services/backup/java/com/android/server/backup/utils/FullBackupUtils.java +0 −72 Original line number Diff line number Diff line Loading @@ -16,23 +16,14 @@ package com.android.server.backup.utils; import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_VERSION; import static com.android.server.backup.BackupManagerService.TAG; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.os.Build; import android.os.ParcelFileDescriptor; import android.util.Slog; import android.util.StringBuilderPrinter; import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; Loading Loading @@ -68,67 +59,4 @@ public class FullBackupUtils { } } } /** * Writes app manifest to the given manifest file. * * @param pkg - app package, which manifest to write. * @param packageManager - {@link PackageManager} instance. * @param manifestFile - target manifest file. * @param withApk - whether include apk or not. * @param withWidgets - whether to write widgets data. * @throws IOException - in case of an error. */ // TODO: withWidgets is not used, decide whether it is needed. public static void writeAppManifest(PackageInfo pkg, PackageManager packageManager, File manifestFile, boolean withApk, boolean withWidgets) throws IOException { // Manifest format. All data are strings ending in LF: // BACKUP_MANIFEST_VERSION, currently 1 // // Version 1: // package name // package's versionCode // platform versionCode // getInstallerPackageName() for this package (maybe empty) // boolean: "1" if archive includes .apk; any other string means not // number of signatures == N // N*: signature byte array in ascii format per Signature.toCharsString() StringBuilder builder = new StringBuilder(4096); StringBuilderPrinter printer = new StringBuilderPrinter(builder); printer.println(Integer.toString(BACKUP_MANIFEST_VERSION)); printer.println(pkg.packageName); printer.println(Long.toString(pkg.getLongVersionCode())); printer.println(Integer.toString(Build.VERSION.SDK_INT)); String installerName = packageManager.getInstallerPackageName(pkg.packageName); printer.println((installerName != null) ? installerName : ""); printer.println(withApk ? "1" : "0"); // write the signature block SigningInfo signingInfo = pkg.signingInfo; if (signingInfo == null) { printer.println("0"); } else { // retrieve the newest sigs to write // TODO (b/73988180) use entire signing history in case of rollbacks Signature[] signatures = signingInfo.getApkContentsSigners(); printer.println(Integer.toString(signatures.length)); for (Signature sig : signatures) { printer.println(sig.toCharsString()); } } FileOutputStream outstream = new FileOutputStream(manifestFile); outstream.write(builder.toString().getBytes()); outstream.close(); // We want the manifest block in the archive stream to be idempotent: // each time we generate a backup stream for the app, we want the manifest // block to be identical. The underlying tar mechanism sees it as a file, // though, and will propagate its mtime, causing the tar header to vary. // Avoid this problem by pinning the mtime to zero. manifestFile.setLastModified(0); } } Loading
core/java/com/android/server/AppWidgetBackupBridge.java +4 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import android.annotation.Nullable; import java.util.List; /** Loading @@ -37,6 +39,8 @@ public class AppWidgetBackupBridge { : null; } /** Returns a byte array of widget data for the specified package or {@code null}. */ @Nullable public static byte[] getWidgetState(String packageName, int userId) { return (sAppWidgetService != null) ? sAppWidgetService.getWidgetState(packageName, userId) Loading
services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java +12 −7 Original line number Diff line number Diff line Loading @@ -9,9 +9,9 @@ import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT import android.app.ApplicationThreadConstants; import android.app.IBackupAgent; import android.app.backup.IBackupCallback; import android.app.backup.FullBackup; import android.app.backup.FullBackupDataOutput; import android.app.backup.IBackupCallback; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -21,6 +21,7 @@ import android.os.SELinux; import android.util.Slog; import com.android.internal.util.Preconditions; import com.android.server.backup.fullbackup.AppMetadataBackupWriter; import com.android.server.backup.remote.ServiceBackupCallback; import com.android.server.backup.utils.FullBackupUtils; Loading Loading @@ -202,16 +203,20 @@ public class KeyValueAdbBackupEngine { public void run() { try { FullBackupDataOutput output = new FullBackupDataOutput(mPipe); AppMetadataBackupWriter writer = new AppMetadataBackupWriter(output, mPackageManager); if (DEBUG) { Slog.d(TAG, "Writing manifest for " + mPackage.packageName); } FullBackupUtils.writeAppManifest( mPackage, mPackageManager, mManifestFile, false, false); FullBackup.backupToTar(mPackage.packageName, FullBackup.KEY_VALUE_DATA_TOKEN, null, mDataDir.getAbsolutePath(), mManifestFile.getAbsolutePath(), output); writer.backupManifest( mPackage, mManifestFile, mDataDir, FullBackup.KEY_VALUE_DATA_TOKEN, /* linkDomain */ null, /* withApk */ false); mManifestFile.delete(); if (DEBUG) { Loading
services/backup/java/com/android/server/backup/fullbackup/AppMetadataBackupWriter.java 0 → 100644 +283 −0 Original line number Diff line number Diff line package com.android.server.backup.fullbackup; import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_VERSION; import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_VERSION; import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN; import static com.android.server.backup.BackupManagerService.MORE_DEBUG; import static com.android.server.backup.BackupManagerService.TAG; import android.annotation.Nullable; import android.app.backup.FullBackup; import android.app.backup.FullBackupDataOutput; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.os.Build; import android.os.Environment; import android.os.UserHandle; import android.util.Log; import android.util.StringBuilderPrinter; import com.android.internal.util.Preconditions; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; /** * Writes the backup of app-specific metadata to {@link FullBackupDataOutput}. This data is not * backed up by the app's backup agent and is written before the agent writes its own data. This * includes the app's: * * <ul> * <li>manifest * <li>widget data * <li>apk * <li>obb content * </ul> */ // TODO(b/113807190): Fix or remove apk and obb implementation (only used for adb). public class AppMetadataBackupWriter { private final FullBackupDataOutput mOutput; private final PackageManager mPackageManager; /** The destination of the backup is specified by {@code output}. */ public AppMetadataBackupWriter(FullBackupDataOutput output, PackageManager packageManager) { mOutput = output; mPackageManager = packageManager; } /** * Back up the app's manifest without specifying a pseudo-directory for the TAR stream. * * @see #backupManifest(PackageInfo, File, File, String, String, boolean) */ public void backupManifest( PackageInfo packageInfo, File manifestFile, File filesDir, boolean withApk) throws IOException { backupManifest( packageInfo, manifestFile, filesDir, /* domain */ null, /* linkDomain */ null, withApk); } /** * Back up the app's manifest. * * <ol> * <li>Write the app's manifest data to the specified temporary file {@code manifestFile}. * <li>Backup the file in TAR format to the backup destination {@link #mOutput}. * </ol> * * <p>Note: {@code domain} and {@code linkDomain} are only used by adb to specify a * pseudo-directory for the TAR stream. */ // TODO(b/113806991): Look into streaming the backup data directly. public void backupManifest( PackageInfo packageInfo, File manifestFile, File filesDir, @Nullable String domain, @Nullable String linkDomain, boolean withApk) throws IOException { byte[] manifestBytes = getManifestBytes(packageInfo, withApk); FileOutputStream outputStream = new FileOutputStream(manifestFile); outputStream.write(manifestBytes); outputStream.close(); // We want the manifest block in the archive stream to be constant each time we generate // a backup stream for the app. However, the underlying TAR mechanism sees it as a file and // will propagate its last modified time. We pin the last modified time to zero to prevent // the TAR header from varying. manifestFile.setLastModified(0); FullBackup.backupToTar( packageInfo.packageName, domain, linkDomain, filesDir.getAbsolutePath(), manifestFile.getAbsolutePath(), mOutput); } /** * Gets the app's manifest as a byte array. All data are strings ending in LF. * * <p>The manifest format is: * * <pre> * BACKUP_MANIFEST_VERSION * package name * package version code * platform version code * installer package name (can be empty) * boolean (1 if archive includes .apk, otherwise 0) * # of signatures N * N* (signature byte array in ascii format per Signature.toCharsString()) * </pre> */ private byte[] getManifestBytes(PackageInfo packageInfo, boolean withApk) { String packageName = packageInfo.packageName; StringBuilder builder = new StringBuilder(4096); StringBuilderPrinter printer = new StringBuilderPrinter(builder); printer.println(Integer.toString(BACKUP_MANIFEST_VERSION)); printer.println(packageName); printer.println(Long.toString(packageInfo.getLongVersionCode())); printer.println(Integer.toString(Build.VERSION.SDK_INT)); String installerName = mPackageManager.getInstallerPackageName(packageName); printer.println((installerName != null) ? installerName : ""); printer.println(withApk ? "1" : "0"); // Write the signature block. SigningInfo signingInfo = packageInfo.signingInfo; if (signingInfo == null) { printer.println("0"); } else { // Retrieve the newest signatures to write. // TODO (b/73988180) use entire signing history in case of rollbacks. Signature[] signatures = signingInfo.getApkContentsSigners(); printer.println(Integer.toString(signatures.length)); for (Signature sig : signatures) { printer.println(sig.toCharsString()); } } return builder.toString().getBytes(); } /** * Backup specified widget data. The widget data is prefaced by a metadata header. * * <ol> * <li>Write a metadata header to the specified temporary file {@code metadataFile}. * <li>Write widget data bytes to the same file. * <li>Backup the file in TAR format to the backup destination {@link #mOutput}. * </ol> * * @throws IllegalArgumentException if the widget data provided is empty. */ // TODO(b/113806991): Look into streaming the backup data directly. public void backupWidget( PackageInfo packageInfo, File metadataFile, File filesDir, byte[] widgetData) throws IOException { Preconditions.checkArgument(widgetData.length > 0, "Can't backup widget with no data."); String packageName = packageInfo.packageName; FileOutputStream fileOutputStream = new FileOutputStream(metadataFile); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream); byte[] metadata = getMetadataBytes(packageName); bufferedOutputStream.write(metadata); // bypassing DataOutputStream writeWidgetData(dataOutputStream, widgetData); bufferedOutputStream.flush(); dataOutputStream.close(); // As with the manifest file, guarantee consistency of the archive metadata for the widget // block by using a fixed last modified time on the metadata file. metadataFile.setLastModified(0); FullBackup.backupToTar( packageName, /* domain */ null, /* linkDomain */ null, filesDir.getAbsolutePath(), metadataFile.getAbsolutePath(), mOutput); } /** * Gets the app's metadata as a byte array. All entries are strings ending in LF. * * <p>The metadata format is: * * <pre> * BACKUP_METADATA_VERSION * package name * </pre> */ private byte[] getMetadataBytes(String packageName) { StringBuilder builder = new StringBuilder(512); StringBuilderPrinter printer = new StringBuilderPrinter(builder); printer.println(Integer.toString(BACKUP_METADATA_VERSION)); printer.println(packageName); return builder.toString().getBytes(); } /** * Write a byte array of widget data to the specified output stream. All integers are binary in * network byte order. * * <p>The widget data format: * * <pre> * 4 : Integer token identifying the widget data blob. * 4 : Integer size of the widget data. * N : Raw bytes of the widget data. * </pre> */ private void writeWidgetData(DataOutputStream out, byte[] widgetData) throws IOException { out.writeInt(BACKUP_WIDGET_METADATA_TOKEN); out.writeInt(widgetData.length); out.write(widgetData); } /** * Backup the app's .apk to the backup destination {@link #mOutput}. Currently only used for * 'adb backup'. */ // TODO(b/113807190): Investigate and potentially remove. public void backupApk(PackageInfo packageInfo) { // TODO: handle backing up split APKs String appSourceDir = packageInfo.applicationInfo.getBaseCodePath(); String apkDir = new File(appSourceDir).getParent(); FullBackup.backupToTar( packageInfo.packageName, FullBackup.APK_TREE_TOKEN, /* linkDomain */ null, apkDir, appSourceDir, mOutput); } /** * Backup the app's .obb files to the backup destination {@link #mOutput}. Currently only used * for 'adb backup'. */ // TODO(b/113807190): Investigate and potentially remove. public void backupObb(PackageInfo packageInfo) { // TODO: migrate this to SharedStorageBackup, since AID_SYSTEM doesn't have access to // external storage. // TODO: http://b/22388012 Environment.UserEnvironment userEnv = new Environment.UserEnvironment(UserHandle.USER_SYSTEM); File obbDir = userEnv.buildExternalStorageAppObbDirs(packageInfo.packageName)[0]; if (obbDir != null) { if (MORE_DEBUG) { Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath()); } File[] obbFiles = obbDir.listFiles(); if (obbFiles != null) { String obbDirName = obbDir.getAbsolutePath(); for (File obb : obbFiles) { FullBackup.backupToTar( packageInfo.packageName, FullBackup.OBB_TREE_TOKEN, /* linkDomain */ null, obbDirName, obb.getAbsolutePath(), mOutput); } } } } }
services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java +102 −168 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/backup/java/com/android/server/backup/utils/FullBackupUtils.java +0 −72 Original line number Diff line number Diff line Loading @@ -16,23 +16,14 @@ package com.android.server.backup.utils; import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_VERSION; import static com.android.server.backup.BackupManagerService.TAG; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.os.Build; import android.os.ParcelFileDescriptor; import android.util.Slog; import android.util.StringBuilderPrinter; import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; Loading Loading @@ -68,67 +59,4 @@ public class FullBackupUtils { } } } /** * Writes app manifest to the given manifest file. * * @param pkg - app package, which manifest to write. * @param packageManager - {@link PackageManager} instance. * @param manifestFile - target manifest file. * @param withApk - whether include apk or not. * @param withWidgets - whether to write widgets data. * @throws IOException - in case of an error. */ // TODO: withWidgets is not used, decide whether it is needed. public static void writeAppManifest(PackageInfo pkg, PackageManager packageManager, File manifestFile, boolean withApk, boolean withWidgets) throws IOException { // Manifest format. All data are strings ending in LF: // BACKUP_MANIFEST_VERSION, currently 1 // // Version 1: // package name // package's versionCode // platform versionCode // getInstallerPackageName() for this package (maybe empty) // boolean: "1" if archive includes .apk; any other string means not // number of signatures == N // N*: signature byte array in ascii format per Signature.toCharsString() StringBuilder builder = new StringBuilder(4096); StringBuilderPrinter printer = new StringBuilderPrinter(builder); printer.println(Integer.toString(BACKUP_MANIFEST_VERSION)); printer.println(pkg.packageName); printer.println(Long.toString(pkg.getLongVersionCode())); printer.println(Integer.toString(Build.VERSION.SDK_INT)); String installerName = packageManager.getInstallerPackageName(pkg.packageName); printer.println((installerName != null) ? installerName : ""); printer.println(withApk ? "1" : "0"); // write the signature block SigningInfo signingInfo = pkg.signingInfo; if (signingInfo == null) { printer.println("0"); } else { // retrieve the newest sigs to write // TODO (b/73988180) use entire signing history in case of rollbacks Signature[] signatures = signingInfo.getApkContentsSigners(); printer.println(Integer.toString(signatures.length)); for (Signature sig : signatures) { printer.println(sig.toCharsString()); } } FileOutputStream outstream = new FileOutputStream(manifestFile); outstream.write(builder.toString().getBytes()); outstream.close(); // We want the manifest block in the archive stream to be idempotent: // each time we generate a backup stream for the app, we want the manifest // block to be identical. The underlying tar mechanism sees it as a file, // though, and will propagate its mtime, causing the tar header to vary. // Avoid this problem by pinning the mtime to zero. manifestFile.setLastModified(0); } }