Merge "Move public static methods to utility classes."

This commit is contained in:
TreeHugger Robot
2017-04-24 17:47:47 +00:00
committed by Android (Google) Code Review
13 changed files with 492 additions and 341 deletions

View File

@@ -16,7 +16,6 @@
package com.android.server.backup;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
import android.app.ActivityManager;
@@ -27,7 +26,6 @@ import android.app.IBackupAgent;
import android.app.PendingIntent;
import android.app.backup.BackupManager;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupProgress;
import android.app.backup.FullBackup;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupManagerMonitor;
@@ -48,11 +46,9 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.HandlerThread;
@@ -76,7 +72,6 @@ import android.util.EventLog;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.StringBuilderPrinter;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.backup.IBackupTransport;
@@ -103,6 +98,9 @@ import com.android.server.backup.params.ClearRetryParams;
import com.android.server.backup.params.RestoreParams;
import com.android.server.backup.restore.ActiveRestoreSession;
import com.android.server.backup.restore.PerformUnifiedRestoreTask;
import com.android.server.backup.utils.AppBackupUtils;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
import com.android.server.backup.utils.BackupObserverUtils;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import libcore.io.IoUtils;
@@ -684,7 +682,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
private HashSet<String> mEverStoredApps = new HashSet<>();
private static final int CURRENT_ANCESTRAL_RECORD_VERSION = 1;
// increment when the schema changes
// increment when the schema changes
private File mTokenFile;
private Set<String> mAncestralPackages = null;
private long mAncestralToken = 0;
@@ -718,49 +716,6 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
return token;
}
// High level policy: apps are generally ineligible for backup if certain conditions apply
public static boolean appIsEligibleForBackup(ApplicationInfo app) {
// 1. their manifest states android:allowBackup="false"
if ((app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) {
return false;
}
// 2. they run as a system-level uid but do not supply their own backup agent
if ((app.uid < Process.FIRST_APPLICATION_UID) && (app.backupAgentName == null)) {
return false;
}
// 3. it is the special shared-storage backup package used for 'adb backup'
if (app.packageName.equals(RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE)) {
return false;
}
return true;
}
// Checks if the app is in a stopped state, that means it won't receive broadcasts.
public static boolean appIsStopped(ApplicationInfo app) {
return ((app.flags & ApplicationInfo.FLAG_STOPPED) != 0);
}
/* does *not* check overall backup eligibility policy! */
public static boolean appGetsFullBackup(PackageInfo pkg) {
if (pkg.applicationInfo.backupAgentName != null) {
// If it has an agent, it gets full backups only if it says so
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FULL_BACKUP_ONLY) != 0;
}
// No agent or fullBackupOnly="true" means we do indeed perform full-data backups for it
return true;
}
/* adb backup: is this app only capable of doing key/value? We say otherwise if
* the app has a backup agent and does not say fullBackupOnly,
*/
public static boolean appIsKeyValueOnly(PackageInfo pkg) {
return !appGetsFullBackup(pkg);
}
// ----- Debug-only backup operation trace -----
public void addBackupTrace(String s) {
if (DEBUG_BACKUP_TRACE) {
@@ -1072,7 +1027,9 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
foundApps.add(pkgName); // all apps that we've addressed already
try {
PackageInfo pkg = mPackageManager.getPackageInfo(pkgName, 0);
if (appGetsFullBackup(pkg) && appIsEligibleForBackup(pkg.applicationInfo)) {
if (AppBackupUtils.appGetsFullBackup(pkg)
&& AppBackupUtils.appIsEligibleForBackup(
pkg.applicationInfo)) {
schedule.add(new FullBackupEntry(pkgName, lastBackup));
} else {
if (DEBUG) {
@@ -1091,7 +1048,9 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
// New apps can arrive "out of band" via OTA and similar, so we also need to
// scan to make sure that we're tracking all full-backup candidates properly
for (PackageInfo app : apps) {
if (appGetsFullBackup(app) && appIsEligibleForBackup(app.applicationInfo)) {
if (AppBackupUtils.appGetsFullBackup(app)
&& AppBackupUtils.appIsEligibleForBackup(
app.applicationInfo)) {
if (!foundApps.contains(app.packageName)) {
if (MORE_DEBUG) {
Slog.i(TAG, "New full backup app " + app.packageName + " found");
@@ -1120,7 +1079,8 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
changed = true;
schedule = new ArrayList<>(apps.size());
for (PackageInfo info : apps) {
if (appGetsFullBackup(info) && appIsEligibleForBackup(info.applicationInfo)) {
if (AppBackupUtils.appGetsFullBackup(info) && AppBackupUtils.appIsEligibleForBackup(
info.applicationInfo)) {
schedule.add(new FullBackupEntry(info.packageName, 0));
}
}
@@ -1587,7 +1547,9 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
for (String packageName : pkgList) {
try {
PackageInfo app = mPackageManager.getPackageInfo(packageName, 0);
if (appGetsFullBackup(app) && appIsEligibleForBackup(app.applicationInfo)) {
if (AppBackupUtils.appGetsFullBackup(app)
&& AppBackupUtils.appIsEligibleForBackup(
app.applicationInfo)) {
enqueueFullBackup(packageName, now);
scheduleNextFullBackupJob(0);
} else {
@@ -1967,16 +1929,18 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
if (packages == null || packages.length < 1) {
Slog.e(TAG, "No packages named for backup request");
sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
monitor = monitorEvent(monitor, BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES,
BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
monitor = BackupManagerMonitorUtils.monitorEvent(monitor,
BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES,
null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
throw new IllegalArgumentException("No packages are provided for backup");
}
IBackupTransport transport = mTransportManager.getCurrentTransportBinder();
if (transport == null) {
sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
monitor = monitorEvent(monitor, BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
monitor = BackupManagerMonitorUtils.monitorEvent(monitor,
BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
return BackupManager.ERROR_TRANSPORT_ABORTED;
}
@@ -1991,18 +1955,18 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
try {
PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
PackageManager.GET_SIGNATURES);
if (!appIsEligibleForBackup(packageInfo.applicationInfo)) {
sendBackupOnPackageResult(observer, packageName,
if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo)) {
BackupObserverUtils.sendBackupOnPackageResult(observer, packageName,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
continue;
}
if (appGetsFullBackup(packageInfo)) {
if (AppBackupUtils.appGetsFullBackup(packageInfo)) {
fullBackupList.add(packageInfo.packageName);
} else {
kvBackupList.add(packageInfo.packageName);
}
} catch (NameNotFoundException e) {
sendBackupOnPackageResult(observer, packageName,
BackupObserverUtils.sendBackupOnPackageResult(observer, packageName,
BackupManager.ERROR_PACKAGE_NOT_FOUND);
}
}
@@ -2019,7 +1983,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
dirName = transport.transportDirName();
} catch (Exception e) {
Slog.e(TAG, "Transport unavailable while attempting backup: " + e.getMessage());
sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
return BackupManager.ERROR_TRANSPORT_ABORTED;
}
@@ -2218,26 +2182,6 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
}
// ----- Full backup/restore to a file/socket -----
public static void routeSocketDataToOutput(ParcelFileDescriptor inPipe, OutputStream out)
throws IOException {
// We do not take close() responsibility for the pipe FD
FileInputStream raw = new FileInputStream(inPipe.getFileDescriptor());
DataInputStream in = new DataInputStream(raw);
byte[] buffer = new byte[32 * 1024];
int chunkTotal;
while ((chunkTotal = in.readInt()) > 0) {
while (chunkTotal > 0) {
int toRead = (chunkTotal > buffer.length) ? buffer.length : chunkTotal;
int nRead = in.read(buffer, 0, toRead);
out.write(buffer, 0, nRead);
chunkTotal -= nRead;
}
}
}
@Override
public void tearDownAgentAndKill(ApplicationInfo app) {
if (app == null) {
@@ -2264,55 +2208,6 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
}
}
// Core logic for performing one package's full backup, gathering the tarball from the
// application and emitting it to the designated OutputStream.
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(Integer.toString(pkg.versionCode));
printer.println(Integer.toString(Build.VERSION.SDK_INT));
String installerName = packageManager.getInstallerPackageName(pkg.packageName);
printer.println((installerName != null) ? installerName : "");
printer.println(withApk ? "1" : "0");
if (pkg.signatures == null) {
printer.println("0");
} else {
printer.println(Integer.toString(pkg.signatures.length));
for (Signature sig : pkg.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);
}
public boolean deviceIsEncrypted() {
try {
return mStorageManager.getEncryptionState()
@@ -2524,7 +2419,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
try {
PackageInfo appInfo = mPackageManager.getPackageInfo(entry.packageName, 0);
if (!appGetsFullBackup(appInfo)) {
if (!AppBackupUtils.appGetsFullBackup(appInfo)) {
// The head app isn't supposed to get full-data backups [any more];
// so we cull it and force a loop around to consider the new head
// app.
@@ -2611,63 +2506,6 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
}
}
// ----- Restore handling -----
// Old style: directly match the stored vs on device signature blocks
public static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
if (target == null) {
return false;
}
// If the target resides on the system partition, we allow it to restore
// data from the like-named package in a restore set even if the signatures
// do not match. (Unlike general applications, those flashed to the system
// partition will be signed with the device's platform certificate, so on
// different phones the same system app will have different signatures.)
if ((target.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
if (MORE_DEBUG) {
Slog.v(TAG,
"System app " + target.packageName + " - skipping sig check");
}
return true;
}
// Allow unsigned apps, but not signed on one device and unsigned on the other
// !!! TODO: is this the right policy?
Signature[] deviceSigs = target.signatures;
if (MORE_DEBUG) {
Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs
+ " device=" + deviceSigs);
}
if ((storedSigs == null || storedSigs.length == 0)
&& (deviceSigs == null || deviceSigs.length == 0)) {
return true;
}
if (storedSigs == null || deviceSigs == null) {
return false;
}
// !!! TODO: this demands that every stored signature match one
// that is present on device, and does not demand the converse.
// Is this this right policy?
int nStored = storedSigs.length;
int nDevice = deviceSigs.length;
for (int i = 0; i < nStored; i++) {
boolean match = false;
for (int j = 0; j < nDevice; j++) {
if (storedSigs[i].equals(deviceSigs[j])) {
match = true;
break;
}
}
if (!match) {
return false;
}
}
return true;
}
// Used by both incremental and full restore
public void restoreWidgetData(String packageName, byte[] widgetData) {
// Apply the restored widget state and generate the ID update for the app
@@ -3738,8 +3576,8 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
try {
PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
PackageManager.GET_SIGNATURES);
if (!appIsEligibleForBackup(packageInfo.applicationInfo) ||
appIsStopped(packageInfo.applicationInfo) ||
if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo) ||
AppBackupUtils.appIsStopped(packageInfo.applicationInfo) ||
appIsDisabled(packageInfo.applicationInfo, mPackageManager)) {
return false;
}
@@ -3747,7 +3585,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
if (transport != null) {
try {
return transport.isAppEligibleForBackup(packageInfo,
appGetsFullBackup(packageInfo));
AppBackupUtils.appGetsFullBackup(packageInfo));
} catch (Exception e) {
Slog.e(TAG, "Unable to ask about eligibility: " + e.getMessage());
}
@@ -3896,44 +3734,6 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
}
}
public static void sendBackupOnUpdate(IBackupObserver observer, String packageName,
BackupProgress progress) {
if (observer != null) {
try {
observer.onUpdate(packageName, progress);
} catch (RemoteException e) {
if (DEBUG) {
Slog.w(TAG, "Backup observer went away: onUpdate");
}
}
}
}
public static void sendBackupOnPackageResult(IBackupObserver observer, String packageName,
int status) {
if (observer != null) {
try {
observer.onResult(packageName, status);
} catch (RemoteException e) {
if (DEBUG) {
Slog.w(TAG, "Backup observer went away: onResult");
}
}
}
}
public static void sendBackupFinished(IBackupObserver observer, int status) {
if (observer != null) {
try {
observer.backupFinished(status);
} catch (RemoteException e) {
if (DEBUG) {
Slog.w(TAG, "Backup observer went away: backupFinished");
}
}
}
}
public Bundle putMonitoringExtra(Bundle extras, String key, String value) {
if (extras == null) {
extras = new Bundle();
@@ -3967,33 +3767,6 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
return extras;
}
public static IBackupManagerMonitor monitorEvent(IBackupManagerMonitor monitor, int id,
PackageInfo pkg, int category, Bundle extras) {
if (monitor != null) {
try {
Bundle bundle = new Bundle();
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID, id);
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY, category);
if (pkg != null) {
bundle.putString(EXTRA_LOG_EVENT_PACKAGE_NAME,
pkg.packageName);
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION,
pkg.versionCode);
}
if (extras != null) {
bundle.putAll(extras);
}
monitor.onEvent(bundle);
return monitor;
} catch (RemoteException e) {
if (DEBUG) {
Slog.w(TAG, "backup manager monitor went away");
}
}
}
return null;
}
@Override
public IBackupManager getBackupManagerBinder() {
return mBackupManagerBinder;

View File

@@ -34,6 +34,7 @@ import android.util.StringBuilderPrinter;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.utils.FullBackupUtils;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
@@ -42,6 +43,10 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Core logic for performing one package's full backup, gathering the tarball from the
* application and emitting it to the designated OutputStream.
*/
public class FullBackupEngine {
private RefactoredBackupManagerService backupManagerService;
@@ -90,7 +95,7 @@ public class FullBackupEngine {
Slog.d(RefactoredBackupManagerService.TAG,
"Writing manifest for " + mPackage.packageName);
}
RefactoredBackupManagerService
FullBackupUtils
.writeAppManifest(mPackage, backupManagerService.getPackageManager(),
mManifestFile, mSendApk,
writeWidgetData);
@@ -211,7 +216,7 @@ public class FullBackupEngine {
t.start();
// Now pull data from the app and stuff it into the output
RefactoredBackupManagerService.routeSocketDataToOutput(pipes[0], mOutput);
FullBackupUtils.routeSocketDataToOutput(pipes[0], mOutput);
if (!backupManagerService.waitUntilOperationComplete(mOpToken)) {
Slog.e(RefactoredBackupManagerService.TAG,

View File

@@ -29,10 +29,14 @@ import android.util.Slog;
import com.android.internal.backup.IObbBackupService;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.utils.FullBackupUtils;
import java.io.IOException;
import java.io.OutputStream;
/**
* Full backup/restore to a file/socket.
*/
public class FullBackupObbConnection implements ServiceConnection {
private RefactoredBackupManagerService backupManagerService;
@@ -72,7 +76,7 @@ public class FullBackupObbConnection implements ServiceConnection {
null, RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
mService.backupObbs(pkg.packageName, pipes[1], token,
backupManagerService.getBackupManagerBinder());
RefactoredBackupManagerService.routeSocketDataToOutput(pipes[0], out);
FullBackupUtils.routeSocketDataToOutput(pipes[0], out);
success = backupManagerService.waitUntilOperationComplete(token);
} catch (Exception e) {
Slog.w(RefactoredBackupManagerService.TAG, "Unable to back up OBBs for " + pkg, e);

View File

@@ -30,6 +30,7 @@ import com.android.server.AppWidgetBackupBridge;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.KeyValueAdbBackupEngine;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.utils.AppBackupUtils;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
@@ -282,14 +283,14 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor
Iterator<Entry<String, PackageInfo>> iter = packagesToBackup.entrySet().iterator();
while (iter.hasNext()) {
PackageInfo pkg = iter.next().getValue();
if (!RefactoredBackupManagerService.appIsEligibleForBackup(pkg.applicationInfo)
|| RefactoredBackupManagerService.appIsStopped(pkg.applicationInfo)) {
if (!AppBackupUtils.appIsEligibleForBackup(pkg.applicationInfo)
|| AppBackupUtils.appIsStopped(pkg.applicationInfo)) {
iter.remove();
if (RefactoredBackupManagerService.DEBUG) {
Slog.i(RefactoredBackupManagerService.TAG, "Package " + pkg.packageName
+ " is not eligible for backup, removing.");
}
} else if (RefactoredBackupManagerService.appIsKeyValueOnly(pkg)) {
} else if (AppBackupUtils.appIsKeyValueOnly(pkg)) {
iter.remove();
if (RefactoredBackupManagerService.DEBUG) {
Slog.i(RefactoredBackupManagerService.TAG, "Package " + pkg.packageName

View File

@@ -39,6 +39,9 @@ import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.FullBackupJob;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.internal.Operation;
import com.android.server.backup.utils.AppBackupUtils;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
import com.android.server.backup.utils.BackupObserverUtils;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -132,7 +135,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
PackageInfo info = backupManagerService.getPackageManager().getPackageInfo(pkg,
PackageManager.GET_SIGNATURES);
mCurrentPackage = info;
if (!RefactoredBackupManagerService.appIsEligibleForBackup(info.applicationInfo)) {
if (!AppBackupUtils.appIsEligibleForBackup(info.applicationInfo)) {
// Cull any packages that have indicated that backups are not permitted,
// that run as system-domain uids but do not define their own backup agents,
// as well as any explicit mention of the 'special' shared-storage agent
@@ -140,49 +143,49 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
if (RefactoredBackupManagerService.MORE_DEBUG) {
Slog.d(TAG, "Ignoring ineligible package " + pkg);
}
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_INELIGIBLE,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
null);
RefactoredBackupManagerService.sendBackupOnPackageResult(mBackupObserver, pkg,
BackupObserverUtils.sendBackupOnPackageResult(mBackupObserver, pkg,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
continue;
} else if (!RefactoredBackupManagerService.appGetsFullBackup(info)) {
} else if (!AppBackupUtils.appGetsFullBackup(info)) {
// Cull any packages that are found in the queue but now aren't supposed
// to get full-data backup operations.
if (RefactoredBackupManagerService.MORE_DEBUG) {
Slog.d(TAG, "Ignoring full-data backup of key/value participant "
+ pkg);
}
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
null);
RefactoredBackupManagerService.sendBackupOnPackageResult(mBackupObserver, pkg,
BackupObserverUtils.sendBackupOnPackageResult(mBackupObserver, pkg,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
continue;
} else if (RefactoredBackupManagerService.appIsStopped(info.applicationInfo)) {
} else if (AppBackupUtils.appIsStopped(info.applicationInfo)) {
// Cull any packages in the 'stopped' state: they've either just been
// installed or have explicitly been force-stopped by the user. In both
// cases we do not want to launch them for backup.
if (RefactoredBackupManagerService.MORE_DEBUG) {
Slog.d(TAG, "Ignoring stopped package " + pkg);
}
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_STOPPED,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
null);
RefactoredBackupManagerService.sendBackupOnPackageResult(mBackupObserver, pkg,
BackupObserverUtils.sendBackupOnPackageResult(mBackupObserver, pkg,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
continue;
}
mPackages.add(info);
} catch (NameNotFoundException e) {
Slog.i(TAG, "Requested package " + pkg + " not found; ignoring");
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_FOUND,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -270,7 +273,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
} else {
monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED;
}
mMonitor = RefactoredBackupManagerService
mMonitor = BackupManagerMonitorUtils
.monitorEvent(mMonitor, monitoringEvent, null,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
null);
@@ -283,7 +286,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
if (mTransport == null) {
Slog.w(TAG, "Transport not present; full data backup not performed");
backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT,
mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
null);
@@ -357,7 +360,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
+ packageName + ": " + preflightResult
+ ", not running backup.");
}
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_ERROR_PREFLIGHT,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -381,7 +384,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
}
totalRead += nRead;
if (mBackupObserver != null && preflightResult > 0) {
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnUpdate(mBackupObserver, packageName,
new BackupProgress(preflightResult, totalRead));
}
@@ -392,7 +395,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
Slog.w(TAG, "Package hit quota limit in-flight " + packageName
+ ": " + totalRead + " of " + quota);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
@@ -470,7 +473,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
}
if (backupPackageStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mBackupObserver, packageName,
BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
if (RefactoredBackupManagerService.DEBUG) {
@@ -481,7 +484,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
"transport rejected");
// Do nothing, clean up, and continue looping.
} else if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mBackupObserver, packageName,
BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
if (RefactoredBackupManagerService.DEBUG) {
@@ -491,7 +494,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
}
// Do nothing, clean up, and continue looping.
} else if (backupPackageStatus == BackupTransport.AGENT_ERROR) {
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mBackupObserver, packageName,
BackupManager.ERROR_AGENT_FAILURE);
Slog.w(TAG, "Application failure for package: " + packageName);
@@ -499,7 +502,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
// Do nothing, clean up, and continue looping.
} else if (backupPackageStatus == BackupManager.ERROR_BACKUP_CANCELLED) {
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mBackupObserver, packageName,
BackupManager.ERROR_BACKUP_CANCELLED);
Slog.w(TAG, "Backup cancelled. package=" + packageName +
@@ -508,7 +511,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
// Do nothing, clean up, and continue looping.
} else if (backupPackageStatus != BackupTransport.TRANSPORT_OK) {
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mBackupObserver, packageName,
BackupManager.ERROR_TRANSPORT_ABORTED);
Slog.w(TAG, "Transport failed; aborting backup: " + backupPackageStatus);
@@ -518,7 +521,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
return;
} else {
// Success!
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mBackupObserver, packageName,
BackupManager.SUCCESS);
EventLog.writeEvent(EventLogTags.FULL_BACKUP_SUCCESS, packageName);
@@ -538,7 +541,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
} catch (Exception e) {
backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
Slog.w(TAG, "Exception trying full transport backup", e);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_EXCEPTION_FULL_BACKUP,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -555,7 +558,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
if (RefactoredBackupManagerService.DEBUG) {
Slog.i(TAG, "Full backup completed with status: " + backupRunStatus);
}
RefactoredBackupManagerService.sendBackupFinished(mBackupObserver, backupRunStatus);
BackupObserverUtils.sendBackupFinished(mBackupObserver, backupRunStatus);
cleanUpPipes(transportPipes);
cleanUpPipes(enginePipes);
@@ -833,7 +836,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
Slog.w(TAG, "Full backup cancel of " + mTarget.packageName);
}
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_CANCEL,
mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
mIsCancelled = true;

View File

@@ -50,6 +50,9 @@ import com.android.server.backup.PackageManagerBackupAgent;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.RefactoredBackupManagerService.BackupState;
import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.utils.AppBackupUtils;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
import com.android.server.backup.utils.BackupObserverUtils;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -242,7 +245,7 @@ public class PerformBackupTask implements BackupRestoreTask {
if (mOriginalQueue.isEmpty() && mPendingFullBackups.isEmpty()) {
Slog.w(TAG, "Backup begun with an empty queue - nothing to do.");
backupManagerService.addBackupTrace("queue empty at begin");
RefactoredBackupManagerService.sendBackupFinished(mObserver, BackupManager.SUCCESS);
BackupObserverUtils.sendBackupFinished(mObserver, BackupManager.SUCCESS);
executeNextState(BackupState.FINAL);
return;
}
@@ -343,7 +346,7 @@ public class PerformBackupTask implements BackupRestoreTask {
// restage everything and try again later.
backupManagerService.resetBackupState(mStateDir); // Just to make sure.
// In case of any other error, it's backup transport error.
RefactoredBackupManagerService.sendBackupFinished(mObserver,
BackupObserverUtils.sendBackupFinished(mObserver,
BackupManager.ERROR_TRANSPORT_ABORTED);
executeNextState(BackupState.FINAL);
}
@@ -380,7 +383,7 @@ public class PerformBackupTask implements BackupRestoreTask {
mCurrentPackage = backupManagerService.getPackageManager().getPackageInfo(
request.packageName,
PackageManager.GET_SIGNATURES);
if (!RefactoredBackupManagerService.appIsEligibleForBackup(
if (!AppBackupUtils.appIsEligibleForBackup(
mCurrentPackage.applicationInfo)) {
// The manifest has changed but we had a stale backup request pending.
// This won't happen again because the app won't be requesting further
@@ -390,14 +393,14 @@ public class PerformBackupTask implements BackupRestoreTask {
backupManagerService.addBackupTrace("skipping - not eligible, completion is noop");
// Shouldn't happen in case of requested backup, as pre-check was done in
// #requestBackup(), except to app update done concurrently
RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver,
BackupObserverUtils.sendBackupOnPackageResult(mObserver,
mCurrentPackage.packageName,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
executeNextState(BackupState.RUNNING_QUEUE);
return;
}
if (RefactoredBackupManagerService.appGetsFullBackup(mCurrentPackage)) {
if (AppBackupUtils.appGetsFullBackup(mCurrentPackage)) {
// It's possible that this app *formerly* was enqueued for key/value backup,
// but has since been updated and now only supports the full-data path.
// Don't proceed with a key/value backup for it in this case.
@@ -407,19 +410,19 @@ public class PerformBackupTask implements BackupRestoreTask {
"skipping - fullBackupOnly, completion is noop");
// Shouldn't happen in case of requested backup, as pre-check was done in
// #requestBackup()
RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver,
BackupObserverUtils.sendBackupOnPackageResult(mObserver,
mCurrentPackage.packageName,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
executeNextState(BackupState.RUNNING_QUEUE);
return;
}
if (RefactoredBackupManagerService.appIsStopped(mCurrentPackage.applicationInfo)) {
if (AppBackupUtils.appIsStopped(mCurrentPackage.applicationInfo)) {
// The app has been force-stopped or cleared or just installed,
// and not yet launched out of that state, so just as it won't
// receive broadcasts, we won't run it for backup.
backupManagerService.addBackupTrace("skipping - stopped");
RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver,
BackupObserverUtils.sendBackupOnPackageResult(mObserver,
mCurrentPackage.packageName,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
executeNextState(BackupState.RUNNING_QUEUE);
@@ -473,14 +476,14 @@ public class PerformBackupTask implements BackupRestoreTask {
backupManagerService.dataChangedImpl(request.packageName);
mStatus = BackupTransport.TRANSPORT_OK;
if (mQueue.isEmpty()) nextState = BackupState.FINAL;
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
BackupManager.ERROR_AGENT_FAILURE);
} else if (mStatus == BackupTransport.AGENT_UNKNOWN) {
// Failed lookup of the app, so we couldn't bring up an agent, but
// we're otherwise fine. Just drop it and go on to the next as usual.
mStatus = BackupTransport.TRANSPORT_OK;
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
BackupManager.ERROR_PACKAGE_NOT_FOUND);
} else {
@@ -577,22 +580,22 @@ public class PerformBackupTask implements BackupRestoreTask {
if (mFullBackupTask != null) {
mFullBackupTask.unregisterTask();
}
RefactoredBackupManagerService.sendBackupFinished(mObserver,
BackupObserverUtils.sendBackupFinished(mObserver,
BackupManager.ERROR_BACKUP_CANCELLED);
} else {
mFullBackupTask.unregisterTask();
switch (mStatus) {
case BackupTransport.TRANSPORT_OK:
RefactoredBackupManagerService.sendBackupFinished(mObserver,
BackupObserverUtils.sendBackupFinished(mObserver,
BackupManager.SUCCESS);
break;
case BackupTransport.TRANSPORT_NOT_INITIALIZED:
RefactoredBackupManagerService.sendBackupFinished(mObserver,
BackupObserverUtils.sendBackupFinished(mObserver,
BackupManager.ERROR_TRANSPORT_ABORTED);
break;
case BackupTransport.TRANSPORT_ERROR:
default:
RefactoredBackupManagerService.sendBackupFinished(mObserver,
BackupObserverUtils.sendBackupFinished(mObserver,
BackupManager.ERROR_TRANSPORT_ABORTED);
break;
}
@@ -834,7 +837,7 @@ public class PerformBackupTask implements BackupRestoreTask {
.addBackupTrace("illegal key " + key + " from " + pkgName);
EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
"bad key");
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY,
mCurrentPackage,
BackupManagerMonitor
@@ -845,7 +848,7 @@ public class PerformBackupTask implements BackupRestoreTask {
backupManagerService.getBackupHandler().removeMessages(
RefactoredBackupManagerService
.MSG_BACKUP_OPERATION_TIMEOUT);
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mObserver, pkgName,
BackupManager.ERROR_AGENT_FAILURE);
errorCleanup();
@@ -920,7 +923,7 @@ public class PerformBackupTask implements BackupRestoreTask {
"no backup data written; not calling transport");
}
backupManagerService.addBackupTrace("no data to send");
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -933,7 +936,7 @@ public class PerformBackupTask implements BackupRestoreTask {
// with the new state file it just created.
mBackupDataName.delete();
mNewStateName.renameTo(mSavedStateName);
RefactoredBackupManagerService
BackupObserverUtils
.sendBackupOnPackageResult(mObserver, pkgName, BackupManager.SUCCESS);
EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, pkgName, size);
backupManagerService.logBackupComplete(pkgName);
@@ -942,21 +945,21 @@ public class PerformBackupTask implements BackupRestoreTask {
// back but proceed with running the rest of the queue.
mBackupDataName.delete();
mNewStateName.delete();
RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver, pkgName,
BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
EventLogTags.writeBackupAgentFailure(pkgName, "Transport rejected");
} else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver, pkgName,
BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
EventLog.writeEvent(EventLogTags.BACKUP_QUOTA_EXCEEDED, pkgName);
} else {
// Actual transport-level failure to communicate the data to the backend
RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver, pkgName,
BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
BackupManager.ERROR_TRANSPORT_ABORTED);
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
}
} catch (Exception e) {
RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver, pkgName,
BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
BackupManager.ERROR_TRANSPORT_ABORTED);
Slog.e(TAG, "Transport error backing up " + pkgName, e);
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
@@ -1021,7 +1024,7 @@ public class PerformBackupTask implements BackupRestoreTask {
EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, logPackageName);
backupManagerService.addBackupTrace(
"cancel of " + logPackageName + ", cancelAll=" + cancelAll);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
backupManagerService.putMonitoringExtra(null,

View File

@@ -59,6 +59,8 @@ import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.FileMetadata;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.fullbackup.FullBackupObbConnection;
import com.android.server.backup.utils.AppBackupUtils;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
@@ -753,7 +755,7 @@ public class FullRestoreEngine extends RestoreEngine {
} else {
// So far so good -- do the signatures match the manifest?
Signature[] sigs = mManifestSignatures.get(info.packageName);
if (RefactoredBackupManagerService.signaturesMatch(sigs, pkg)) {
if (AppBackupUtils.signaturesMatch(sigs, pkg)) {
// If this is a system-uid app without a declared backup agent,
// don't restore any of the file data.
if ((pkg.applicationInfo.uid < Process.FIRST_APPLICATION_UID)
@@ -883,7 +885,7 @@ public class FullRestoreEngine extends RestoreEngine {
EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
BackupManagerMonitor.EXTRA_LOG_WIDGET_PACKAGE_NAME, pkg);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_WIDGET_METADATA_MISMATCH,
null,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -897,7 +899,7 @@ public class FullRestoreEngine extends RestoreEngine {
info.packageName);
monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION,
null,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -977,13 +979,13 @@ public class FullRestoreEngine extends RestoreEngine {
// such packages are signed with the platform cert instead of
// the app developer's cert, so they're different on every
// device.
if (RefactoredBackupManagerService.signaturesMatch(sigs,
if (AppBackupUtils.signaturesMatch(sigs,
pkgInfo)) {
if ((pkgInfo.applicationInfo.flags
& ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
Slog.i(RefactoredBackupManagerService.TAG,
"Package has restoreAnyVersion; taking data");
mMonitor = RefactoredBackupManagerService.monitorEvent(
mMonitor = BackupManagerMonitorUtils.monitorEvent(
mMonitor,
LOG_EVENT_ID_RESTORE_ANY_VERSION,
pkgInfo,
@@ -994,7 +996,7 @@ public class FullRestoreEngine extends RestoreEngine {
Slog.i(RefactoredBackupManagerService.TAG,
"Sig + version match; taking data");
policy = RestorePolicy.ACCEPT;
mMonitor = RefactoredBackupManagerService.monitorEvent(
mMonitor = BackupManagerMonitorUtils.monitorEvent(
mMonitor,
LOG_EVENT_ID_VERSIONS_MATCH,
pkgInfo,
@@ -1016,7 +1018,7 @@ public class FullRestoreEngine extends RestoreEngine {
Slog.i(RefactoredBackupManagerService.TAG,
"Data requires newer version "
+ version + "; ignoring");
mMonitor = RefactoredBackupManagerService
mMonitor = BackupManagerMonitorUtils
.monitorEvent(mMonitor,
LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER,
pkgInfo,
@@ -1035,7 +1037,7 @@ public class FullRestoreEngine extends RestoreEngine {
"Restore manifest signatures do not match "
+ "installed application for "
+ info.packageName);
mMonitor = RefactoredBackupManagerService.monitorEvent(
mMonitor = BackupManagerMonitorUtils.monitorEvent(
mMonitor,
LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH,
pkgInfo,
@@ -1046,7 +1048,7 @@ public class FullRestoreEngine extends RestoreEngine {
Slog.w(RefactoredBackupManagerService.TAG,
"Package " + info.packageName
+ " is system level with no agent");
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
LOG_EVENT_ID_SYSTEM_APP_NO_AGENT,
pkgInfo,
LOG_EVENT_CATEGORY_AGENT,
@@ -1058,7 +1060,7 @@ public class FullRestoreEngine extends RestoreEngine {
"Restore manifest from "
+ info.packageName + " but allowBackup=false");
}
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE,
pkgInfo,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -1083,7 +1085,7 @@ public class FullRestoreEngine extends RestoreEngine {
monitoringExtras = backupManagerService.putMonitoringExtra(
monitoringExtras,
EXTRA_LOG_POLICY_ALLOW_APKS, mAllowApks);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
LOG_EVENT_ID_APK_NOT_INSTALLED,
null,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -1094,7 +1096,7 @@ public class FullRestoreEngine extends RestoreEngine {
Slog.i(RefactoredBackupManagerService.TAG,
"Cannot restore package " + info.packageName
+ " without the matching .apk");
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK,
null,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -1105,7 +1107,7 @@ public class FullRestoreEngine extends RestoreEngine {
Slog.i(RefactoredBackupManagerService.TAG,
"Missing signature on backed-up package "
+ info.packageName);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
LOG_EVENT_ID_MISSING_SIGNATURE,
null,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -1120,7 +1122,7 @@ public class FullRestoreEngine extends RestoreEngine {
EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
EXTRA_LOG_MANIFEST_PACKAGE_NAME, manifestPackage);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE,
null,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -1134,7 +1136,7 @@ public class FullRestoreEngine extends RestoreEngine {
EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_UNKNOWN_VERSION,
null,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -1144,7 +1146,7 @@ public class FullRestoreEngine extends RestoreEngine {
} catch (NumberFormatException e) {
Slog.w(RefactoredBackupManagerService.TAG,
"Corrupt restore manifest for package " + info.packageName);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_CORRUPT_MANIFEST,
null,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,

View File

@@ -41,6 +41,7 @@ import com.android.server.backup.KeyValueAdbRestoreEngine;
import com.android.server.backup.PackageManagerBackupAgent;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.fullbackup.FullBackupObbConnection;
import com.android.server.backup.utils.AppBackupUtils;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
@@ -994,7 +995,7 @@ public class PerformAdbRestoreTask implements Runnable {
} else {
// So far so good -- do the signatures match the manifest?
Signature[] sigs = mManifestSignatures.get(info.packageName);
if (RefactoredBackupManagerService.signaturesMatch(sigs, pkg)) {
if (AppBackupUtils.signaturesMatch(sigs, pkg)) {
// If this is a system-uid app without a declared backup agent,
// don't restore any of the file data.
if ((pkg.applicationInfo.uid < Process.FIRST_APPLICATION_UID)
@@ -1188,7 +1189,7 @@ public class PerformAdbRestoreTask implements Runnable {
// such packages are signed with the platform cert instead of
// the app developer's cert, so they're different on every
// device.
if (RefactoredBackupManagerService.signaturesMatch(sigs,
if (AppBackupUtils.signaturesMatch(sigs,
pkgInfo)) {
if ((pkgInfo.applicationInfo.flags
& ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {

View File

@@ -47,6 +47,8 @@ import com.android.server.backup.BackupUtils;
import com.android.server.backup.PackageManagerBackupAgent;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.utils.AppBackupUtils;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
import libcore.io.IoUtils;
@@ -194,7 +196,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
continue;
}
if (RefactoredBackupManagerService.appIsEligibleForBackup(
if (AppBackupUtils.appIsEligibleForBackup(
info.applicationInfo)) {
mAcceptSet.add(info);
}
@@ -351,7 +353,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
if (desc == null) {
Slog.e(RefactoredBackupManagerService.TAG,
"No restore metadata available; halting");
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
@@ -363,7 +365,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
desc.getPackageName())) {
Slog.e(RefactoredBackupManagerService.TAG, "Required package metadata but got "
+ desc.getPackageName());
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_NO_PM_METADATA_RECEIVED,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
@@ -397,7 +399,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
if (!mPmAgent.hasMetadata()) {
Slog.e(RefactoredBackupManagerService.TAG,
"PM agent has no metadata, so not restoring");
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
@@ -418,7 +420,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
// If we lost the transport at any time, halt
Slog.e(RefactoredBackupManagerService.TAG,
"Unable to contact transport for restore: " + e.getMessage());
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_LOST_TRANSPORT,
null,
BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
@@ -477,7 +479,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
// Whoops, we thought we could restore this package but it
// turns out not to be present. Skip it.
Slog.e(RefactoredBackupManagerService.TAG, "Package not present: " + pkgName);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_PRESENT,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -503,7 +505,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
metaInfo.versionCode);
monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -524,7 +526,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
metaInfo.versionCode);
monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -578,7 +580,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
Slog.i(RefactoredBackupManagerService.TAG, "Data exists for package " + packageName
+ " but app has no agent; skipping");
}
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_APP_HAS_NO_AGENT, mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
@@ -591,7 +593,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage)) {
Slog.w(RefactoredBackupManagerService.TAG,
"Signature mismatch restoring " + packageName);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH, mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
@@ -607,7 +609,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
if (mAgent == null) {
Slog.w(RefactoredBackupManagerService.TAG,
"Can't find backup agent for " + packageName);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_CANT_FIND_AGENT, mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
@@ -988,7 +990,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
"Full-data restore target timed out; shutting down");
}
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_TIMEOUT,
mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
mEngineThread.handleTimeout();
@@ -1282,7 +1284,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
backupManagerService.removeOperation(mEphemeralOpToken);
Slog.e(RefactoredBackupManagerService.TAG,
"Timeout restoring application " + mCurrentPackage.packageName);
mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT,
mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,

View File

@@ -0,0 +1,131 @@
package com.android.server.backup.utils;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.Signature;
import android.os.Process;
import android.util.Slog;
import com.android.server.backup.RefactoredBackupManagerService;
/**
* Utility methods wrapping operations on ApplicationInfo and PackageInfo.
*/
public class AppBackupUtils {
/**
* Returns whether app is eligible for backup.
*
* High level policy: apps are generally ineligible for backup if certain conditions apply. The
* conditions are:
*
* <ol>
* <li>their manifest states android:allowBackup="false"
* <li>they run as a system-level uid but do not supply their own backup agent
* <li>it is the special shared-storage backup package used for 'adb backup'
* </ol>
*/
public static boolean appIsEligibleForBackup(ApplicationInfo app) {
// 1. their manifest states android:allowBackup="false"
if ((app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) {
return false;
}
// 2. they run as a system-level uid but do not supply their own backup agent
if ((app.uid < Process.FIRST_APPLICATION_UID) && (app.backupAgentName == null)) {
return false;
}
// 3. it is the special shared-storage backup package used for 'adb backup'
if (app.packageName.equals(RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE)) {
return false;
}
return true;
}
/**
* Checks if the app is in a stopped state, that means it won't receive broadcasts.
*/
public static boolean appIsStopped(ApplicationInfo app) {
return ((app.flags & ApplicationInfo.FLAG_STOPPED) != 0);
}
/**
* Returns whether the app can get full backup. Does *not* check overall backup eligibility
* policy!
*/
public static boolean appGetsFullBackup(PackageInfo pkg) {
if (pkg.applicationInfo.backupAgentName != null) {
// If it has an agent, it gets full backups only if it says so
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FULL_BACKUP_ONLY) != 0;
}
// No agent or fullBackupOnly="true" means we do indeed perform full-data backups for it
return true;
}
/**
* Returns whether the app is only capable of doing key/value. We say it's not if it allows full
* backup, and it is otherwise.
*/
public static boolean appIsKeyValueOnly(PackageInfo pkg) {
return !appGetsFullBackup(pkg);
}
/**
* Old style: directly match the stored vs on device signature blocks.
*/
public static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
if (target == null) {
return false;
}
// If the target resides on the system partition, we allow it to restore
// data from the like-named package in a restore set even if the signatures
// do not match. (Unlike general applications, those flashed to the system
// partition will be signed with the device's platform certificate, so on
// different phones the same system app will have different signatures.)
if ((target.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
if (RefactoredBackupManagerService.MORE_DEBUG) {
Slog.v(RefactoredBackupManagerService.TAG,
"System app " + target.packageName + " - skipping sig check");
}
return true;
}
// Allow unsigned apps, but not signed on one device and unsigned on the other
// !!! TODO: is this the right policy?
Signature[] deviceSigs = target.signatures;
if (RefactoredBackupManagerService.MORE_DEBUG) {
Slog.v(RefactoredBackupManagerService.TAG, "signaturesMatch(): stored=" + storedSigs
+ " device=" + deviceSigs);
}
if ((storedSigs == null || storedSigs.length == 0)
&& (deviceSigs == null || deviceSigs.length == 0)) {
return true;
}
if (storedSigs == null || deviceSigs == null) {
return false;
}
// !!! TODO: this demands that every stored signature match one
// that is present on device, and does not demand the converse.
// Is this this right policy?
int nStored = storedSigs.length;
int nDevice = deviceSigs.length;
for (int i = 0; i < nStored; i++) {
boolean match = false;
for (int j = 0; j < nDevice; j++) {
if (storedSigs[i].equals(deviceSigs[j])) {
match = true;
break;
}
}
if (!match) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,56 @@
package com.android.server.backup.utils;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.IBackupManagerMonitor;
import android.content.pm.PackageInfo;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.backup.RefactoredBackupManagerService;
/**
* Utility methods to communicate with BackupManagerMonitor.
*/
public class BackupManagerMonitorUtils {
/**
* Notifies monitor about the event.
*
* Calls {@link IBackupManagerMonitor#onEvent(Bundle)} with a bundle representing current event.
*
* @param monitor - implementation of {@link IBackupManagerMonitor} to notify.
* @param id - event id.
* @param pkg - package event is related to.
* @param category - event category.
* @param extras - additional event data.
* @return <code>monitor</code> if call succeeded and <code>null</code> otherwise.
*/
public static IBackupManagerMonitor monitorEvent(IBackupManagerMonitor monitor, int id,
PackageInfo pkg, int category, Bundle extras) {
if (monitor != null) {
try {
Bundle bundle = new Bundle();
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID, id);
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY, category);
if (pkg != null) {
bundle.putString(EXTRA_LOG_EVENT_PACKAGE_NAME,
pkg.packageName);
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION,
pkg.versionCode);
}
if (extras != null) {
bundle.putAll(extras);
}
monitor.onEvent(bundle);
return monitor;
} catch (RemoteException e) {
if (RefactoredBackupManagerService.DEBUG) {
Slog.w(RefactoredBackupManagerService.TAG, "backup manager monitor went away");
}
}
}
return null;
}
}

View File

@@ -0,0 +1,66 @@
package com.android.server.backup.utils;
import android.app.backup.BackupProgress;
import android.app.backup.IBackupObserver;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.backup.RefactoredBackupManagerService;
/**
* Utility methods to communicate with BackupObserver.
*/
public class BackupObserverUtils {
/**
* Wraps {@link IBackupObserver#onUpdate(String, BackupProgress)} to handle RemoteException,
* so that the caller doesn't have to.
*/
public static void sendBackupOnUpdate(IBackupObserver observer, String packageName,
BackupProgress progress) {
if (observer != null) {
try {
observer.onUpdate(packageName, progress);
} catch (RemoteException e) {
if (RefactoredBackupManagerService.DEBUG) {
Slog.w(RefactoredBackupManagerService.TAG,
"Backup observer went away: onUpdate");
}
}
}
}
/**
* Wraps {@link IBackupObserver#onResult(String, int)} to handle RemoteException, so that the
* caller doesn't have to.
*/
public static void sendBackupOnPackageResult(IBackupObserver observer, String packageName,
int status) {
if (observer != null) {
try {
observer.onResult(packageName, status);
} catch (RemoteException e) {
if (RefactoredBackupManagerService.DEBUG) {
Slog.w(RefactoredBackupManagerService.TAG,
"Backup observer went away: onResult");
}
}
}
}
/**
* Wraps {@link IBackupObserver#backupFinished(int)} to handle RemoteException, so that the
* caller doesn't have to.
*/
public static void sendBackupFinished(IBackupObserver observer, int status) {
if (observer != null) {
try {
observer.backupFinished(status);
} catch (RemoteException e) {
if (RefactoredBackupManagerService.DEBUG) {
Slog.w(RefactoredBackupManagerService.TAG,
"Backup observer went away: backupFinished");
}
}
}
}
}

View File

@@ -0,0 +1,104 @@
package com.android.server.backup.utils;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.util.StringBuilderPrinter;
import com.android.server.backup.RefactoredBackupManagerService;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Low-level utility methods for full backup.
*/
public class FullBackupUtils {
/**
* Reads data from pipe and writes it to the stream in chunks of up to 32KB.
*
* @param inPipe - pipe to read the data from.
* @param out - stream to write the data to.
* @throws IOException - in case of an error.
*/
public static void routeSocketDataToOutput(ParcelFileDescriptor inPipe, OutputStream out)
throws IOException {
// We do not take close() responsibility for the pipe FD
FileInputStream raw = new FileInputStream(inPipe.getFileDescriptor());
DataInputStream in = new DataInputStream(raw);
byte[] buffer = new byte[32 * 1024];
int chunkTotal;
while ((chunkTotal = in.readInt()) > 0) {
while (chunkTotal > 0) {
int toRead = (chunkTotal > buffer.length) ? buffer.length : chunkTotal;
int nRead = in.read(buffer, 0, toRead);
out.write(buffer, 0, nRead);
chunkTotal -= nRead;
}
}
}
/**
* 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(RefactoredBackupManagerService.BACKUP_MANIFEST_VERSION));
printer.println(pkg.packageName);
printer.println(Integer.toString(pkg.versionCode));
printer.println(Integer.toString(Build.VERSION.SDK_INT));
String installerName = packageManager.getInstallerPackageName(pkg.packageName);
printer.println((installerName != null) ? installerName : "");
printer.println(withApk ? "1" : "0");
if (pkg.signatures == null) {
printer.println("0");
} else {
printer.println(Integer.toString(pkg.signatures.length));
for (Signature sig : pkg.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);
}
}