diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java index 677efd0d6de39..c7a4d613a080f 100644 --- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java @@ -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 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 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; diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java index fbb7a127b95f4..72eeea0eec11f 100644 --- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java +++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java @@ -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, diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java index 826db582f994b..34ff949957440 100644 --- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java +++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java @@ -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); diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java index 174a38a52cac6..172702efe6456 100644 --- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java +++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java @@ -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> 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 diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java index 0a728d715d225..5e7069efdb65d 100644 --- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java +++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java @@ -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; diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java index aedc6ff2aaced..81da8290a218d 100644 --- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java +++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java @@ -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, diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java index 4a0e2e0dce734..4e6bde63ab157 100644 --- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java +++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java @@ -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, diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java index f06a679745bc4..5794f4f6f5d36 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java @@ -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) { diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java index 1c1709aa26045..643936e11b0df 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java @@ -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, diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java new file mode 100644 index 0000000000000..a32635e326081 --- /dev/null +++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java @@ -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: + * + *
    + *
  1. their manifest states android:allowBackup="false" + *
  2. they run as a system-level uid but do not supply their own backup agent + *
  3. it is the special shared-storage backup package used for 'adb backup' + *
+ */ + 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; + } +} diff --git a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java new file mode 100644 index 0000000000000..447962cb4ec45 --- /dev/null +++ b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java @@ -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 monitor if call succeeded and null 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; + } +} diff --git a/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java new file mode 100644 index 0000000000000..b5e5e08289eaa --- /dev/null +++ b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java @@ -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"); + } + } + } + } +} diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java new file mode 100644 index 0000000000000..bfb4b259c8f66 --- /dev/null +++ b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java @@ -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); + } +}