summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Christopher Tate <ctate@google.com> 2011-06-24 14:58:49 -0700
committer Christopher Tate <ctate@google.com> 2011-07-06 14:40:32 -0700
commit79ec80db70d788f35aa13346e4684ecbd401bd84 (patch)
treefd18f64033def7461692f9542bf9e5f01afe2fe0
parentbe87cc945b5b094060cbc77b77383aefc60265e4 (diff)
Make full backup API available to apps
New methods for full backup/restore have been added to BackupAgent (still hidden): onFullBackup() and onRestoreFile(). The former is the entry point for a full app backup to adb/socket/etc: the app then writes all of its files, entire, to the output. During restore, the latter new callback is invoked, once for each file being restored. The full backup/restore interface does not use the previously-defined BackupDataInput / BackupDataOutput classes, because those classes provide an API designed for incremental key/value data structuring. Instead, a new FullBackupDataOutput class has been introduced, through which we restrict apps' abilities to write data during a full backup operation to *only* writing entire on-disk files via a new BackupAgent method called fullBackupFile(). "FullBackupAgent" exists now solely as a concrete shell class that can be instantiated in the case of apps that do not have their own BackupAgent implementations. Along with the API change, responsibility for backing up the .apk file and OBB container has been moved into the framework rather than have the application side of the transaction do it. Change-Id: I12849b06b1a6e4c44d080587c1e9828a52b70dae
-rw-r--r--api/current.txt94
-rw-r--r--core/java/android/app/ActivityThread.java11
-rw-r--r--core/java/android/app/IBackupAgent.aidl20
-rw-r--r--core/java/android/app/backup/BackupAgent.java289
-rw-r--r--core/java/android/app/backup/FullBackup.java49
-rw-r--r--core/java/android/app/backup/FullBackupAgent.java192
-rw-r--r--core/java/android/app/backup/FullBackupDataOutput.java21
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java11
-rw-r--r--core/java/android/content/pm/PackageParser.java11
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/res/res/values/attrs_manifest.xml8
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--packages/SettingsProvider/AndroidManifest.xml1
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java109
-rw-r--r--packages/SharedStorageBackup/AndroidManifest.xml2
-rw-r--r--packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java21
-rw-r--r--services/java/com/android/server/BackupManagerService.java73
-rw-r--r--services/java/com/android/server/SystemBackupAgent.java2
18 files changed, 530 insertions, 387 deletions
diff --git a/api/current.txt b/api/current.txt
index d009a64f355c..d7e3cb30e8ac 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -183,14 +183,14 @@ package android {
public static final class R.attr {
ctor public R.attr();
field public static final int absListViewStyle = 16842858; // 0x101006a
- field public static final int accessibilityEventTypes = 16843650; // 0x1010382
- field public static final int accessibilityFeedbackType = 16843652; // 0x1010384
- field public static final int accessibilityFlags = 16843654; // 0x1010386
+ field public static final int accessibilityEventTypes = 16843649; // 0x1010381
+ field public static final int accessibilityFeedbackType = 16843651; // 0x1010383
+ field public static final int accessibilityFlags = 16843653; // 0x1010385
field public static final int accountPreferences = 16843423; // 0x101029f
field public static final int accountType = 16843407; // 0x101028f
field public static final int action = 16842797; // 0x101002d
field public static final int actionBarSize = 16843499; // 0x10102eb
- field public static final int actionBarSplitStyle = 16843676; // 0x101039c
+ field public static final int actionBarSplitStyle = 16843675; // 0x101039b
field public static final int actionBarStyle = 16843470; // 0x10102ce
field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
field public static final int actionBarTabStyle = 16843507; // 0x10102f3
@@ -206,9 +206,9 @@ package android {
field public static final int actionModeCopyDrawable = 16843538; // 0x1010312
field public static final int actionModeCutDrawable = 16843537; // 0x1010311
field public static final int actionModePasteDrawable = 16843539; // 0x1010313
- field public static final int actionModeSelectAllDrawable = 16843648; // 0x1010380
+ field public static final int actionModeSelectAllDrawable = 16843647; // 0x101037f
field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
- field public static final int actionProviderClass = 16843678; // 0x101039e
+ field public static final int actionProviderClass = 16843677; // 0x101039d
field public static final int actionViewClass = 16843516; // 0x10102fc
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
@@ -220,7 +220,7 @@ package android {
field public static final int alertDialogIcon = 16843605; // 0x1010355
field public static final int alertDialogStyle = 16842845; // 0x101005d
field public static final int alertDialogTheme = 16843529; // 0x1010309
- field public static final int alignmentMode = 16843642; // 0x101037a
+ field public static final int alignmentMode = 16843641; // 0x1010379
field public static final int allContactsName = 16843468; // 0x10102cc
field public static final int allowBackup = 16843392; // 0x1010280
field public static final int allowClearUserData = 16842757; // 0x1010005
@@ -262,7 +262,7 @@ package android {
field public static final int borderlessButtonStyle = 16843563; // 0x101032b
field public static final int bottom = 16843184; // 0x10101b0
field public static final int bottomBright = 16842957; // 0x10100cd
- field public static final int bottomChevronDrawable = 16843661; // 0x101038d
+ field public static final int bottomChevronDrawable = 16843660; // 0x101038c
field public static final int bottomDark = 16842953; // 0x10100c9
field public static final int bottomLeftRadius = 16843179; // 0x10101ab
field public static final int bottomMedium = 16842958; // 0x10100ce
@@ -281,7 +281,7 @@ package android {
field public static final int cacheColorHint = 16843009; // 0x1010101
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
- field public static final int canRetrieveWindowContent = 16843655; // 0x1010387
+ field public static final int canRetrieveWindowContent = 16843654; // 0x1010386
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
field public static final deprecated int capitalize = 16843113; // 0x1010169
field public static final int centerBright = 16842956; // 0x10100cc
@@ -314,9 +314,9 @@ package android {
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
- field public static final int columnCount = 16843639; // 0x1010377
+ field public static final int columnCount = 16843638; // 0x1010376
field public static final int columnDelay = 16843215; // 0x10101cf
- field public static final int columnOrderPreserved = 16843640; // 0x1010378
+ field public static final int columnOrderPreserved = 16843639; // 0x1010377
field public static final int columnWidth = 16843031; // 0x1010117
field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365
field public static final int completionHint = 16843122; // 0x1010172
@@ -429,7 +429,7 @@ package android {
field public static final int fastScrollTextColor = 16843609; // 0x1010359
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
- field public static final int feedbackCount = 16843667; // 0x1010393
+ field public static final int feedbackCount = 16843666; // 0x1010392
field public static final int fillAfter = 16843197; // 0x10101bd
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillEnabled = 16843343; // 0x101024f
@@ -462,7 +462,6 @@ package android {
field public static final int fromXScale = 16843202; // 0x10101c2
field public static final int fromYDelta = 16843208; // 0x10101c8
field public static final int fromYScale = 16843204; // 0x10101c4
- field public static final int fullBackupAgent = 16843635; // 0x1010373
field public static final int fullBright = 16842954; // 0x10100ca
field public static final int fullDark = 16842950; // 0x10100c6
field public static final int functionalTest = 16842787; // 0x1010023
@@ -483,7 +482,7 @@ package android {
field public static final int hand_hour = 16843011; // 0x1010103
field public static final int hand_minute = 16843012; // 0x1010104
field public static final int handle = 16843354; // 0x101025a
- field public static final int handleDrawable = 16843657; // 0x1010389
+ field public static final int handleDrawable = 16843656; // 0x1010388
field public static final int handleProfiling = 16842786; // 0x1010022
field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
field public static final int hardwareAccelerated = 16843475; // 0x10102d3
@@ -492,12 +491,12 @@ package android {
field public static final int headerDividersEnabled = 16843310; // 0x101022e
field public static final int height = 16843093; // 0x1010155
field public static final int hint = 16843088; // 0x1010150
- field public static final int hitRadius = 16843664; // 0x1010390
+ field public static final int hitRadius = 16843663; // 0x101038f
field public static final int homeAsUpIndicator = 16843531; // 0x101030b
field public static final int homeLayout = 16843549; // 0x101031d
field public static final int horizontalDivider = 16843053; // 0x101012d
field public static final int horizontalGap = 16843327; // 0x101023f
- field public static final int horizontalOffset = 16843669; // 0x1010395
+ field public static final int horizontalOffset = 16843668; // 0x1010394
field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
field public static final int horizontalSpacing = 16843028; // 0x1010114
field public static final int host = 16842792; // 0x1010028
@@ -543,7 +542,7 @@ package android {
field public static final int installLocation = 16843447; // 0x10102b7
field public static final int interpolator = 16843073; // 0x1010141
field public static final int isAlwaysSyncable = 16843571; // 0x1010333
- field public static final int isAuxiliary = 16843649; // 0x1010381
+ field public static final int isAuxiliary = 16843648; // 0x1010380
field public static final int isDefault = 16843297; // 0x1010221
field public static final int isIndicator = 16843079; // 0x1010147
field public static final int isModifier = 16843334; // 0x1010246
@@ -597,30 +596,30 @@ package android {
field public static final int layout_centerInParent = 16843151; // 0x101018f
field public static final int layout_centerVertical = 16843153; // 0x1010191
field public static final int layout_column = 16843084; // 0x101014c
- field public static final int layout_columnSpan = 16843645; // 0x101037d
+ field public static final int layout_columnSpan = 16843644; // 0x101037c
field public static final int layout_gravity = 16842931; // 0x10100b3
field public static final int layout_height = 16842997; // 0x10100f5
- field public static final int layout_heightSpec = 16843647; // 0x101037f
+ field public static final int layout_heightSpec = 16843646; // 0x101037e
field public static final int layout_margin = 16842998; // 0x10100f6
field public static final int layout_marginBottom = 16843002; // 0x10100fa
- field public static final int layout_marginEnd = 16843675; // 0x101039b
+ field public static final int layout_marginEnd = 16843674; // 0x101039a
field public static final int layout_marginLeft = 16842999; // 0x10100f7
field public static final int layout_marginRight = 16843001; // 0x10100f9
- field public static final int layout_marginStart = 16843674; // 0x101039a
+ field public static final int layout_marginStart = 16843673; // 0x1010399
field public static final int layout_marginTop = 16843000; // 0x10100f8
- field public static final int layout_row = 16843643; // 0x101037b
- field public static final int layout_rowSpan = 16843644; // 0x101037c
+ field public static final int layout_row = 16843642; // 0x101037a
+ field public static final int layout_rowSpan = 16843643; // 0x101037b
field public static final int layout_scale = 16843155; // 0x1010193
field public static final int layout_span = 16843085; // 0x101014d
field public static final int layout_toLeftOf = 16843138; // 0x1010182
field public static final int layout_toRightOf = 16843139; // 0x1010183
field public static final int layout_weight = 16843137; // 0x1010181
field public static final int layout_width = 16842996; // 0x10100f4
- field public static final int layout_widthSpec = 16843646; // 0x101037e
+ field public static final int layout_widthSpec = 16843645; // 0x101037d
field public static final int layout_x = 16843135; // 0x101017f
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
- field public static final int leftChevronDrawable = 16843658; // 0x101038a
+ field public static final int leftChevronDrawable = 16843657; // 0x1010389
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -632,8 +631,8 @@ package android {
field public static final int listDividerAlertDialog = 16843525; // 0x1010305
field public static final int listPopupWindowStyle = 16843519; // 0x10102ff
field public static final int listPreferredItemHeight = 16842829; // 0x101004d
- field public static final int listPreferredItemHeightLarge = 16843670; // 0x1010396
- field public static final int listPreferredItemHeightSmall = 16843671; // 0x1010397
+ field public static final int listPreferredItemHeightLarge = 16843669; // 0x1010395
+ field public static final int listPreferredItemHeightSmall = 16843670; // 0x1010396
field public static final int listSelector = 16843003; // 0x10100fb
field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
field public static final int listViewStyle = 16842868; // 0x1010074
@@ -679,7 +678,7 @@ package android {
field public static final int nextFocusUp = 16842979; // 0x10100e3
field public static final int noHistory = 16843309; // 0x101022d
field public static final int normalScreens = 16843397; // 0x1010285
- field public static final int notificationTimeout = 16843653; // 0x1010385
+ field public static final int notificationTimeout = 16843652; // 0x1010384
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
field public static final deprecated int numeric = 16843109; // 0x1010165
@@ -693,17 +692,17 @@ package android {
field public static final int orderingFromXml = 16843239; // 0x10101e7
field public static final int orientation = 16842948; // 0x10100c4
field public static final int outAnimation = 16843128; // 0x1010178
- field public static final int outerRadius = 16843663; // 0x101038f
+ field public static final int outerRadius = 16843662; // 0x101038e
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
- field public static final int packageNames = 16843651; // 0x1010383
+ field public static final int packageNames = 16843650; // 0x1010382
field public static final int padding = 16842965; // 0x10100d5
field public static final int paddingBottom = 16842969; // 0x10100d9
- field public static final int paddingEnd = 16843673; // 0x1010399
+ field public static final int paddingEnd = 16843672; // 0x1010398
field public static final int paddingLeft = 16842966; // 0x10100d6
field public static final int paddingRight = 16842968; // 0x10100d8
- field public static final int paddingStart = 16843672; // 0x1010398
+ field public static final int paddingStart = 16843671; // 0x1010397
field public static final int paddingTop = 16842967; // 0x10100d7
field public static final int panelBackground = 16842846; // 0x101005e
field public static final int panelColorBackground = 16842849; // 0x1010061
@@ -784,17 +783,17 @@ package android {
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
field public static final int right = 16843183; // 0x10101af
- field public static final int rightChevronDrawable = 16843659; // 0x101038b
+ field public static final int rightChevronDrawable = 16843658; // 0x101038a
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
field public static final int ringtoneType = 16843257; // 0x10101f9
field public static final int rotation = 16843558; // 0x1010326
field public static final int rotationX = 16843559; // 0x1010327
field public static final int rotationY = 16843560; // 0x1010328
- field public static final int rowCount = 16843637; // 0x1010375
+ field public static final int rowCount = 16843636; // 0x1010374
field public static final int rowDelay = 16843216; // 0x10101d0
field public static final int rowEdgeFlags = 16843329; // 0x1010241
field public static final int rowHeight = 16843058; // 0x1010132
- field public static final int rowOrderPreserved = 16843638; // 0x1010376
+ field public static final int rowOrderPreserved = 16843637; // 0x1010375
field public static final int saveEnabled = 16842983; // 0x10100e7
field public static final int scaleGravity = 16843262; // 0x10101fe
field public static final int scaleHeight = 16843261; // 0x10101fd
@@ -860,7 +859,7 @@ package android {
field public static final int smallIcon = 16843422; // 0x101029e
field public static final int smallScreens = 16843396; // 0x1010284
field public static final int smoothScrollbar = 16843313; // 0x1010231
- field public static final int snapMargin = 16843666; // 0x1010392
+ field public static final int snapMargin = 16843665; // 0x1010391
field public static final int soundEffectsEnabled = 16843285; // 0x1010215
field public static final int spacing = 16843027; // 0x1010113
field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087
@@ -908,7 +907,7 @@ package android {
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int suggestActionMsg = 16843228; // 0x10101dc
field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd
- field public static final int suggestionsEnabled = 16843636; // 0x1010374
+ field public static final int suggestionsEnabled = 16843635; // 0x1010373
field public static final int summary = 16843241; // 0x10101e9
field public static final int summaryColumn = 16843426; // 0x10102a2
field public static final int summaryOff = 16843248; // 0x10101f0
@@ -925,7 +924,7 @@ package android {
field public static final int tag = 16842961; // 0x10100d1
field public static final int targetActivity = 16843266; // 0x1010202
field public static final int targetClass = 16842799; // 0x101002f
- field public static final int targetDrawables = 16843656; // 0x1010388
+ field public static final int targetDrawables = 16843655; // 0x1010387
field public static final int targetPackage = 16842785; // 0x1010021
field public static final int targetSdkVersion = 16843376; // 0x1010270
field public static final int taskAffinity = 16842770; // 0x1010012
@@ -976,7 +975,7 @@ package android {
field public static final int textColorTertiary = 16843282; // 0x1010212
field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
field public static final int textCursorDrawable = 16843618; // 0x1010362
- field public static final int textDirection = 16843677; // 0x101039d
+ field public static final int textDirection = 16843676; // 0x101039c
field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -1016,7 +1015,7 @@ package android {
field public static final int toYScale = 16843205; // 0x10101c5
field public static final int top = 16843182; // 0x10101ae
field public static final int topBright = 16842955; // 0x10100cb
- field public static final int topChevronDrawable = 16843660; // 0x101038c
+ field public static final int topChevronDrawable = 16843659; // 0x101038b
field public static final int topDark = 16842951; // 0x10100c7
field public static final int topLeftRadius = 16843177; // 0x10101a9
field public static final int topOffset = 16843352; // 0x1010258
@@ -1032,7 +1031,7 @@ package android {
field public static final int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
- field public static final int useDefaultMargins = 16843641; // 0x1010379
+ field public static final int useDefaultMargins = 16843640; // 0x1010378
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
field public static final int userVisible = 16843409; // 0x1010291
@@ -1046,10 +1045,10 @@ package android {
field public static final int verticalCorrection = 16843322; // 0x101023a
field public static final int verticalDivider = 16843054; // 0x101012e
field public static final int verticalGap = 16843328; // 0x1010240
- field public static final int verticalOffset = 16843668; // 0x1010394
+ field public static final int verticalOffset = 16843667; // 0x1010393
field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
field public static final int verticalSpacing = 16843029; // 0x1010115
- field public static final int vibrationDuration = 16843665; // 0x1010391
+ field public static final int vibrationDuration = 16843664; // 0x1010390
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1066,7 +1065,7 @@ package android {
field public static final int wallpaperIntraOpenExitAnimation = 16843416; // 0x1010298
field public static final int wallpaperOpenEnterAnimation = 16843411; // 0x1010293
field public static final int wallpaperOpenExitAnimation = 16843412; // 0x1010294
- field public static final int waveDrawable = 16843662; // 0x101038e
+ field public static final int waveDrawable = 16843661; // 0x101038d
field public static final int webTextViewStyle = 16843449; // 0x10102b9
field public static final int webViewStyle = 16842885; // 0x1010085
field public static final int weekDayTextAppearance = 16843592; // 0x1010348
@@ -3737,7 +3736,11 @@ package android.app.backup {
method public abstract void onBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor) throws java.io.IOException;
method public void onCreate();
method public void onDestroy();
+ method public void onFullBackup(android.app.backup.FullBackupDataOutput) throws java.io.IOException;
method public abstract void onRestore(android.app.backup.BackupDataInput, int, android.os.ParcelFileDescriptor) throws java.io.IOException;
+ method public void onRestoreFile(android.os.ParcelFileDescriptor, long, java.io.File, int, long, long) throws java.io.IOException;
+ field public static final int TYPE_DIRECTORY = 2; // 0x2
+ field public static final int TYPE_FILE = 1; // 0x1
}
public class BackupAgentHelper extends android.app.backup.BackupAgent {
@@ -3789,6 +3792,9 @@ package android.app.backup {
method public void writeNewStateDescription(android.os.ParcelFileDescriptor);
}
+ public class FullBackupDataOutput {
+ }
+
public abstract class RestoreObserver {
ctor public RestoreObserver();
method public void onUpdate(int, java.lang.String);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1ec7a964e5cd..eee14fb1a5b3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2013,15 +2013,10 @@ public final class ActivityThread {
BackupAgent agent = null;
String classname = data.appInfo.backupAgentName;
- if (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
- || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL) {
+ // full backup operation but no app-supplied agent? use the default implementation
+ if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
+ || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) {
classname = "android.app.backup.FullBackupAgent";
- if ((data.appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
- // system packages can supply their own full-backup agent
- if (data.appInfo.fullBackupAgentName != null) {
- classname = data.appInfo.fullBackupAgentName;
- }
- }
}
try {
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 8af78fadfc44..087f83c396dd 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -51,7 +51,6 @@ oneway interface IBackupAgent {
void doBackup(in ParcelFileDescriptor oldState,
in ParcelFileDescriptor data,
in ParcelFileDescriptor newState,
- boolean storeApk,
int token, IBackupManager callbackBinder);
/**
@@ -81,6 +80,25 @@ oneway interface IBackupAgent {
in ParcelFileDescriptor newState, int token, IBackupManager callbackBinder);
/**
+ * Perform a "full" backup to the given file descriptor. The output file is presumed
+ * to be a socket or other non-seekable, write-only data sink. When this method is
+ * called, the app should write all of its files to the output.
+ *
+ * @param data Write-only file to receive the backed-up file content stream.
+ * The data must be formatted correctly for the resulting archive to be
+ * legitimate, so that will be tightly controlled by the available API.
+ *
+ * @param token Opaque token identifying this transaction. This must
+ * be echoed back to the backup service binder once the agent is
+ * finished restoring the application based on the restore data
+ * contents.
+ *
+ * @param callbackBinder Binder on which to indicate operation completion,
+ * passed here as a convenience to the agent.
+ */
+ void doFullBackup(in ParcelFileDescriptor data, int token, IBackupManager callbackBinder);
+
+ /**
* Restore a single "file" to the application. The file was typically obtained from
* a full-backup dataset. The agent reads 'size' bytes of file content
* from the provided file descriptor.
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 63f325870f91..65c73f9b5eb8 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -20,13 +20,22 @@ import android.app.IBackupAgent;
import android.app.backup.IBackupManager;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.pm.ApplicationInfo;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
+import java.io.File;
import java.io.IOException;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+import libcore.io.OsConstants;
+import libcore.io.StructStat;
/**
* Provides the central interface between an
@@ -87,6 +96,24 @@ public abstract class BackupAgent extends ContextWrapper {
private static final String TAG = "BackupAgent";
private static final boolean DEBUG = true;
+ /** @hide */
+ public static final int TYPE_EOF = 0;
+
+ /**
+ * During a full restore, indicates that the file system object being restored
+ * is an ordinary file.
+ */
+ public static final int TYPE_FILE = 1;
+
+ /**
+ * During a full restore, indicates that the file system object being restored
+ * is a directory.
+ */
+ public static final int TYPE_DIRECTORY = 2;
+
+ /** @hide */
+ public static final int TYPE_SYMLINK = 3;
+
public BackupAgent() {
super(null);
}
@@ -179,18 +206,240 @@ public abstract class BackupAgent extends ContextWrapper {
throws IOException;
/**
+ * The default implementation backs up the entirety of the application's "owned"
+ * file system trees to the output.
+ */
+ public void onFullBackup(FullBackupDataOutput data) throws IOException {
+ ApplicationInfo appInfo = getApplicationInfo();
+
+ String rootDir = new File(appInfo.dataDir).getAbsolutePath();
+ String filesDir = getFilesDir().getAbsolutePath();
+ String databaseDir = getDatabasePath("foo").getParentFile().getAbsolutePath();
+ String sharedPrefsDir = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
+ String cacheDir = getCacheDir().getAbsolutePath();
+ String libDir = (appInfo.nativeLibraryDir != null)
+ ? new File(appInfo.nativeLibraryDir).getAbsolutePath()
+ : null;
+
+ // Filters, the scan queue, and the set of resulting entities
+ HashSet<String> filterSet = new HashSet<String>();
+ String packageName = getPackageName();
+
+ // Okay, start with the app's root tree, but exclude all of the canonical subdirs
+ if (libDir != null) {
+ filterSet.add(libDir);
+ }
+ filterSet.add(cacheDir);
+ filterSet.add(databaseDir);
+ filterSet.add(sharedPrefsDir);
+ filterSet.add(filesDir);
+ fullBackupFileTree(packageName, FullBackup.ROOT_TREE_TOKEN, rootDir, filterSet, data);
+
+ // Now do the same for the files dir, db dir, and shared prefs dir
+ filterSet.add(rootDir);
+ filterSet.remove(filesDir);
+ fullBackupFileTree(packageName, FullBackup.DATA_TREE_TOKEN, filesDir, filterSet, data);
+
+ filterSet.add(filesDir);
+ filterSet.remove(databaseDir);
+ fullBackupFileTree(packageName, FullBackup.DATABASE_TREE_TOKEN, databaseDir, filterSet, data);
+
+ filterSet.add(databaseDir);
+ filterSet.remove(sharedPrefsDir);
+ fullBackupFileTree(packageName, FullBackup.SHAREDPREFS_TREE_TOKEN, sharedPrefsDir, filterSet, data);
+ }
+
+ /**
+ * Write an entire file as part of a full-backup operation. The file's contents
+ * will be delivered to the backup destination along with the metadata necessary
+ * to place it with the proper location and permissions on the device where the
+ * data is restored.
* @hide
+ *
+ * @param context The BackupAgent that is calling this method. It is an error to
+ * call it from something other than a running BackupAgent instance.
+ * @param file The file to be backed up. The file must exist and be readable by
+ * the caller.
+ * @param output The destination to which the backed-up file data will be sent.
+ */
+ public final void fullBackupFile(File file, FullBackupDataOutput output) {
+ // Look up where all of our various well-defined dir trees live on this device
+ String mainDir;
+ String filesDir;
+ String dbDir;
+ String spDir;
+ String cacheDir;
+ String libDir;
+
+ ApplicationInfo appInfo = getApplicationInfo();
+
+ mainDir = new File(appInfo.dataDir).getAbsolutePath();
+ filesDir = getFilesDir().getAbsolutePath();
+ dbDir = getDatabasePath("foo").getParentFile().getAbsolutePath();
+ spDir = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
+ cacheDir = getCacheDir().getAbsolutePath();
+ libDir = (appInfo.nativeLibraryDir == null) ? null
+ : new File(appInfo.nativeLibraryDir).getAbsolutePath();
+
+ // Now figure out which well-defined tree the file is placed in, working from
+ // most to least specific. We also specifically exclude the lib and cache dirs.
+ String filePath = file.getAbsolutePath();
+
+ if (filePath.startsWith(cacheDir) || filePath.startsWith(libDir)) {
+ Log.w(TAG, "lib and cache files are not backed up");
+ return;
+ }
+
+ final String domain;
+ String rootpath = null;
+ if (filePath.startsWith(dbDir)) {
+ domain = FullBackup.DATABASE_TREE_TOKEN;
+ rootpath = dbDir;
+ } else if (filePath.startsWith(spDir)) {
+ domain = FullBackup.SHAREDPREFS_TREE_TOKEN;
+ rootpath = spDir;
+ } else if (filePath.startsWith(filesDir)) {
+ domain = FullBackup.DATA_TREE_TOKEN;
+ rootpath = filesDir;
+ } else if (filePath.startsWith(mainDir)) {
+ domain = FullBackup.ROOT_TREE_TOKEN;
+ rootpath = mainDir;
+ } else {
+ Log.w(TAG, "File " + filePath + " is in an unsupported location; skipping");
+ return;
+ }
+
+ // And now that we know where it lives, semantically, back it up appropriately
+ Log.i(TAG, "backupFile() of " + filePath + " => domain=" + domain
+ + " rootpath=" + rootpath);
+ FullBackup.backupToTar(getPackageName(), domain, null, rootpath, filePath,
+ output.getData());
+ }
+
+ /**
+ * Scan the dir tree (if it actually exists) and process each entry we find. If the
+ * 'excludes' parameter is non-null, it is consulted each time a new file system entity
+ * is visited to see whether that entity (and its subtree, if appropriate) should be
+ * omitted from the backup process.
+ *
+ * @hide
+ */
+ protected final void fullBackupFileTree(String packageName, String domain, String rootPath,
+ HashSet<String> excludes, FullBackupDataOutput output) {
+ File rootFile = new File(rootPath);
+ if (rootFile.exists()) {
+ LinkedList<File> scanQueue = new LinkedList<File>();
+ scanQueue.add(rootFile);
+
+ while (scanQueue.size() > 0) {
+ File file = scanQueue.remove(0);
+ String filePath = file.getAbsolutePath();
+
+ // prune this subtree?
+ if (excludes != null && excludes.contains(filePath)) {
+ continue;
+ }
+
+ // If it's a directory, enqueue its contents for scanning.
+ try {
+ StructStat stat = Libcore.os.lstat(filePath);
+ if (OsConstants.S_ISLNK(stat.st_mode)) {
+ if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file);
+ continue;
+ } else if (OsConstants.S_ISDIR(stat.st_mode)) {
+ File[] contents = file.listFiles();
+ if (contents != null) {
+ for (File entry : contents) {
+ scanQueue.add(0, entry);
+ }
+ }
+ }
+ } catch (ErrnoException e) {
+ if (DEBUG) Log.w(TAG, "Error scanning file " + file + " : " + e);
+ continue;
+ }
+
+ // Finally, back this file up before proceeding
+ FullBackup.backupToTar(packageName, domain, null, rootPath, filePath,
+ output.getData());
+ }
+ }
+ }
+
+ /**
+ * Handle the data delivered via the given file descriptor during a full restore
+ * operation. The agent is given the path to the file's original location as well
+ * as its size and metadata.
+ * <p>
+ * The file descriptor can only be read for {@code size} bytes; attempting to read
+ * more data has undefined behavior.
+ * <p>
+ * The default implementation creates the destination file/directory and populates it
+ * with the data from the file descriptor, then sets the file's access mode and
+ * modification time to match the restore arguments.
+ *
+ * @param data A read-only file descriptor from which the agent can read {@code size}
+ * bytes of file data.
+ * @param size The number of bytes of file content to be restored to the given
+ * destination. If the file system object being restored is a directory, {@code size}
+ * will be zero.
+ * @param destination The File on disk to be restored with the given data.
+ * @param type The kind of file system object being restored. This will be either
+ * {@link BackupAgent#TYPE_FILE} or {@link BackupAgent#TYPE_DIRECTORY}.
+ * @param mode The access mode to be assigned to the destination after its data is
+ * written. This is in the standard format used by {@code chmod()}.
+ * @param mtime The modification time of the file when it was backed up, suitable to
+ * be assigned to the file after its data is written.
+ * @throws IOException
*/
public void onRestoreFile(ParcelFileDescriptor data, long size,
- int type, String domain, String path, long mode, long mtime)
+ File destination, int type, long mode, long mtime)
throws IOException {
- // empty stub implementation
+ FullBackup.restoreFile(data, size, type, mode, mtime, destination);
}
/**
- * Package-private, used only for dispatching an extra step during full backup
+ * Only specialized platform agents should overload this entry point to support
+ * restores to crazy non-app locations.
+ * @hide
*/
- void onSaveApk(BackupDataOutput data) {
+ protected void onRestoreFile(ParcelFileDescriptor data, long size,
+ int type, String domain, String path, long mode, long mtime)
+ throws IOException {
+ String basePath = null;
+
+ if (DEBUG) Log.d(TAG, "onRestoreFile() size=" + size + " type=" + type
+ + " domain=" + domain + " relpath=" + path + " mode=" + mode
+ + " mtime=" + mtime);
+
+ // Parse out the semantic domains into the correct physical location
+ if (domain.equals(FullBackup.DATA_TREE_TOKEN)) {
+ basePath = getFilesDir().getAbsolutePath();
+ } else if (domain.equals(FullBackup.DATABASE_TREE_TOKEN)) {
+ basePath = getDatabasePath("foo").getParentFile().getAbsolutePath();
+ } else if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) {
+ basePath = new File(getApplicationInfo().dataDir).getAbsolutePath();
+ } else if (domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)) {
+ basePath = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
+ } else if (domain.equals(FullBackup.CACHE_TREE_TOKEN)) {
+ basePath = getCacheDir().getAbsolutePath();
+ } else {
+ // Not a supported location
+ Log.i(TAG, "Data restored from non-app domain " + domain + ", ignoring");
+ }
+
+ // Now that we've figured out where the data goes, send it on its way
+ if (basePath != null) {
+ File outFile = new File(basePath, path);
+ if (DEBUG) Log.i(TAG, "[" + domain + " : " + path + "] mapped to " + outFile.getPath());
+ onRestoreFile(data, size, outFile, type, mode, mtime);
+ } else {
+ // Not a supported output location? We need to consume the data
+ // anyway, so just use the default "copy the data out" implementation
+ // with a null destination.
+ if (DEBUG) Log.i(TAG, "[ skipping data from unsupported domain " + domain + "]");
+ FullBackup.restoreFile(data, size, type, mode, mtime, null);
+ }
}
// ----- Core implementation -----
@@ -215,7 +464,6 @@ public abstract class BackupAgent extends ContextWrapper {
public void doBackup(ParcelFileDescriptor oldState,
ParcelFileDescriptor data,
ParcelFileDescriptor newState,
- boolean storeApk,
int token, IBackupManager callbackBinder) throws RemoteException {
// Ensure that we're running with the app's normal permission level
long ident = Binder.clearCallingIdentity();
@@ -223,10 +471,6 @@ public abstract class BackupAgent extends ContextWrapper {
if (DEBUG) Log.v(TAG, "doBackup() invoked");
BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
- if (storeApk) {
- onSaveApk(output);
- }
-
try {
BackupAgent.this.onBackup(oldState, output, newState);
} catch (IOException ex) {
@@ -273,6 +517,33 @@ public abstract class BackupAgent extends ContextWrapper {
}
@Override
+ public void doFullBackup(ParcelFileDescriptor data,
+ int token, IBackupManager callbackBinder) {
+ // Ensure that we're running with the app's normal permission level
+ long ident = Binder.clearCallingIdentity();
+
+ if (DEBUG) Log.v(TAG, "doFullBackup() invoked");
+ BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
+
+ try {
+ BackupAgent.this.onFullBackup(new FullBackupDataOutput(data));
+ } catch (IOException ex) {
+ Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+ throw new RuntimeException(ex);
+ } catch (RuntimeException ex) {
+ Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+ throw ex;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ // we'll time out anyway, so we're safe
+ }
+ }
+ }
+
+ @Override
public void doRestoreFile(ParcelFileDescriptor data, long size,
int type, String domain, String path, long mode, long mtime,
int token, IBackupManager callbackBinder) throws RemoteException {
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 3b70e19ad244..d7f1c9f0fab4 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -16,6 +16,9 @@
package android.app.backup;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.ParcelFileDescriptor;
import android.util.Log;
@@ -29,7 +32,8 @@ import libcore.io.Libcore;
/**
* Global constant definitions et cetera related to the full-backup-to-fd
- * binary format.
+ * binary format. Nothing in this namespace is part of any API; it's all
+ * hidden details of the current implementation gathered into one location.
*
* @hide
*/
@@ -52,18 +56,41 @@ public class FullBackup {
public static final String FULL_RESTORE_INTENT_ACTION = "fullrest";
public static final String CONF_TOKEN_INTENT_EXTRA = "conftoken";
- public static final int TYPE_EOF = 0;
- public static final int TYPE_FILE = 1;
- public static final int TYPE_DIRECTORY = 2;
- public static final int TYPE_SYMLINK = 3;
-
+ /**
+ * @hide
+ */
static public native int backupToTar(String packageName, String domain,
String linkdomain, String rootpath, String path, BackupDataOutput output);
- static public void restoreToFile(ParcelFileDescriptor data,
- long size, int type, long mode, long mtime, File outFile,
- boolean doChmod) throws IOException {
- if (type == FullBackup.TYPE_DIRECTORY) {
+ /**
+ * Copy data from a socket to the given File location on permanent storage. The
+ * modification time and access mode of the resulting file will be set if desired.
+ * If the {@code type} parameter indicates that the result should be a directory,
+ * the socket parameter may be {@code null}; even if it is valid, no data will be
+ * read from it in this case.
+ * <p>
+ * If the {@code mode} argument is negative, then the resulting output file will not
+ * have its access mode or last modification time reset as part of this operation.
+ *
+ * @param data Socket supplying the data to be copied to the output file. If the
+ * output is a directory, this may be {@code null}.
+ * @param size Number of bytes of data to copy from the socket to the file. At least
+ * this much data must be available through the {@code data} parameter.
+ * @param type Must be either {@link BackupAgent#TYPE_FILE} for ordinary file data
+ * or {@link BackupAgent#TYPE_DIRECTORY} for a directory.
+ * @param mode Unix-style file mode (as used by the chmod(2) syscall) to be set on
+ * the output file or directory. If this parameter is negative then neither
+ * the mode nor the mtime parameters will be used.
+ * @param mtime A timestamp in the standard Unix epoch that will be imposed as the
+ * last modification time of the output file. if the {@code mode} parameter is
+ * negative then this parameter will be ignored.
+ * @param outFile Location within the filesystem to place the data. This must point
+ * to a location that is writeable by the caller, prefereably using an absolute path.
+ * @throws IOException
+ */
+ static public void restoreFile(ParcelFileDescriptor data,
+ long size, int type, long mode, long mtime, File outFile) throws IOException {
+ if (type == BackupAgent.TYPE_DIRECTORY) {
// Canonically a directory has no associated content, so we don't need to read
// anything from the pipe in this case. Just create the directory here and
// drop down to the final metadata adjustment.
@@ -117,7 +144,7 @@ public class FullBackup {
}
// Now twiddle the state to match the backup, assuming all went well
- if (doChmod && outFile != null) {
+ if (mode >= 0 && outFile != null) {
try {
Libcore.os.chmod(outFile.getPath(), (int)mode);
} catch (ErrnoException e) {
diff --git a/core/java/android/app/backup/FullBackupAgent.java b/core/java/android/app/backup/FullBackupAgent.java
index df1c3639bc58..faea76aee148 100644
--- a/core/java/android/app/backup/FullBackupAgent.java
+++ b/core/java/android/app/backup/FullBackupAgent.java
@@ -16,210 +16,26 @@
package android.app.backup;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Environment;
import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import libcore.io.Libcore;
-import libcore.io.ErrnoException;
-import libcore.io.OsConstants;
-import libcore.io.StructStat;
-
-import java.io.File;
import java.io.IOException;
-import java.util.HashSet;
-import java.util.LinkedList;
/**
- * Backs up an application's entire /data/data/&lt;package&gt;/... file system. This
- * class is used by the desktop full backup mechanism and is not intended for direct
- * use by applications.
+ * Simple concrete class that merely provides the default BackupAgent full backup/restore
+ * implementations for applications that do not supply their own.
*
* {@hide}
*/
public class FullBackupAgent extends BackupAgent {
- // !!! TODO: turn off debugging
- private static final String TAG = "FullBackupAgent";
- private static final boolean DEBUG = true;
-
- PackageManager mPm;
-
- private String mMainDir;
- private String mFilesDir;
- private String mDatabaseDir;
- private String mSharedPrefsDir;
- private String mCacheDir;
- private String mLibDir;
-
- private File NULL_FILE;
-
- @Override
- public void onCreate() {
- NULL_FILE = new File("/dev/null");
-
- mPm = getPackageManager();
- try {
- ApplicationInfo appInfo = mPm.getApplicationInfo(getPackageName(), 0);
- mMainDir = new File(appInfo.dataDir).getAbsolutePath();
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Unable to find package " + getPackageName());
- throw new RuntimeException(e);
- }
-
- mFilesDir = getFilesDir().getAbsolutePath();
- mDatabaseDir = getDatabasePath("foo").getParentFile().getAbsolutePath();
- mSharedPrefsDir = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
- mCacheDir = getCacheDir().getAbsolutePath();
-
- ApplicationInfo app = getApplicationInfo();
- mLibDir = (app.nativeLibraryDir != null)
- ? new File(app.nativeLibraryDir).getAbsolutePath()
- : null;
- }
-
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
- // Filters, the scan queue, and the set of resulting entities
- HashSet<String> filterSet = new HashSet<String>();
- String packageName = getPackageName();
-
- // Okay, start with the app's root tree, but exclude all of the canonical subdirs
- if (mLibDir != null) {
- filterSet.add(mLibDir);
- }
- filterSet.add(mCacheDir);
- filterSet.add(mDatabaseDir);
- filterSet.add(mSharedPrefsDir);
- filterSet.add(mFilesDir);
- processTree(packageName, FullBackup.ROOT_TREE_TOKEN, mMainDir, filterSet, data);
-
- // Now do the same for the files dir, db dir, and shared prefs dir
- filterSet.add(mMainDir);
- filterSet.remove(mFilesDir);
- processTree(packageName, FullBackup.DATA_TREE_TOKEN, mFilesDir, filterSet, data);
-
- filterSet.add(mFilesDir);
- filterSet.remove(mDatabaseDir);
- processTree(packageName, FullBackup.DATABASE_TREE_TOKEN, mDatabaseDir, filterSet, data);
-
- filterSet.add(mDatabaseDir);
- filterSet.remove(mSharedPrefsDir);
- processTree(packageName, FullBackup.SHAREDPREFS_TREE_TOKEN, mSharedPrefsDir, filterSet, data);
+ // Doesn't do incremental backup/restore
}
- // Scan the dir tree (if it actually exists) and process each entry we find. If the
- // 'excludes' parameter is non-null, it is consulted each time a new file system entity
- // is visited to see whether that entity (and its subtree, if appropriate) should be
- // omitted from the backup process.
- protected void processTree(String packageName, String domain, String rootPath,
- HashSet<String> excludes, BackupDataOutput data) {
- File rootFile = new File(rootPath);
- if (rootFile.exists()) {
- LinkedList<File> scanQueue = new LinkedList<File>();
- scanQueue.add(rootFile);
-
- while (scanQueue.size() > 0) {
- File file = scanQueue.remove(0);
- String filePath = file.getAbsolutePath();
-
- // prune this subtree?
- if (excludes != null && excludes.contains(filePath)) {
- continue;
- }
-
- // If it's a directory, enqueue its contents for scanning.
- try {
- StructStat stat = Libcore.os.lstat(filePath);
- if (OsConstants.S_ISLNK(stat.st_mode)) {
- if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file);
- continue;
- } else if (OsConstants.S_ISDIR(stat.st_mode)) {
- File[] contents = file.listFiles();
- if (contents != null) {
- for (File entry : contents) {
- scanQueue.add(0, entry);
- }
- }
- }
- } catch (ErrnoException e) {
- if (DEBUG) Log.w(TAG, "Error scanning file " + file + " : " + e);
- continue;
- }
-
- // Finally, back this file up before proceeding
- FullBackup.backupToTar(packageName, domain, null, rootPath, filePath, data);
- }
- }
- }
-
- @Override
- void onSaveApk(BackupDataOutput data) {
- ApplicationInfo app = getApplicationInfo();
- if (DEBUG) Log.i(TAG, "APK flags: system=" + ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0)
- + " updated=" + ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)
- + " locked=" + ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) );
- if (DEBUG) Log.i(TAG, "codepath: " + getPackageCodePath());
-
- // Forward-locked apps, system-bundled .apks, etc are filtered out before we get here
- final String pkgName = getPackageName();
- final String apkDir = new File(getPackageCodePath()).getParent();
- FullBackup.backupToTar(pkgName, FullBackup.APK_TREE_TOKEN, null,
- apkDir, getPackageCodePath(), data);
-
- // Save associated .obb content if it exists and we did save the apk
- // check for .obb and save those too
- final File obbDir = Environment.getExternalStorageAppObbDirectory(pkgName);
- if (obbDir != null) {
- if (DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath());
- File[] obbFiles = obbDir.listFiles();
- if (obbFiles != null) {
- final String obbDirName = obbDir.getAbsolutePath();
- for (File obb : obbFiles) {
- FullBackup.backupToTar(pkgName, FullBackup.OBB_TREE_TOKEN, null,
- obbDirName, obb.getAbsolutePath(), data);
- }
- }
- }
- }
-
- /**
- * Dummy -- We're never used for restore of an incremental dataset
- */
@Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
- }
-
- /**
- * Restore the described file from the given pipe.
- */
- @Override
- public void onRestoreFile(ParcelFileDescriptor data, long size,
- int type, String domain, String relpath, long mode, long mtime)
- throws IOException {
- String basePath = null;
- File outFile = null;
-
- if (DEBUG) Log.d(TAG, "onRestoreFile() size=" + size + " type=" + type
- + " domain=" + domain + " relpath=" + relpath + " mode=" + mode
- + " mtime=" + mtime);
-
- // Parse out the semantic domains into the correct physical location
- if (domain.equals(FullBackup.DATA_TREE_TOKEN)) basePath = mFilesDir;
- else if (domain.equals(FullBackup.DATABASE_TREE_TOKEN)) basePath = mDatabaseDir;
- else if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) basePath = mMainDir;
- else if (domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)) basePath = mSharedPrefsDir;
-
- // Not a supported output location? We need to consume the data
- // anyway, so send it to /dev/null
- outFile = (basePath != null) ? new File(basePath, relpath) : null;
- if (DEBUG) Log.i(TAG, "[" + domain + " : " + relpath + "] mapped to " + outFile.getPath());
-
- // Now that we've figured out where the data goes, send it on its way
- FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, true);
+ // Doesn't do incremental backup/restore
}
}
diff --git a/core/java/android/app/backup/FullBackupDataOutput.java b/core/java/android/app/backup/FullBackupDataOutput.java
new file mode 100644
index 000000000000..99dab1f76018
--- /dev/null
+++ b/core/java/android/app/backup/FullBackupDataOutput.java
@@ -0,0 +1,21 @@
+package android.app.backup;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Provides the interface through which a {@link BackupAgent} writes entire files
+ * to a full backup data set, via its {@link BackupAgent#onFullBackup(FullBackupDataOutput)}
+ * method.
+ */
+public class FullBackupDataOutput {
+ // Currently a name-scoping shim around BackupDataOutput
+ private BackupDataOutput mData;
+
+ /** @hide */
+ public FullBackupDataOutput(ParcelFileDescriptor fd) {
+ mData = new BackupDataOutput(fd.getFileDescriptor());
+ }
+
+ /** @hide */
+ public BackupDataOutput getData() { return mData; }
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 454cb3195316..ddb6ef0d2f53 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -91,15 +91,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public String backupAgentName;
/**
- * Class implementing the package's *full* backup functionality. This
- * is not usable except by system-installed packages. It can be the same
- * as the backupAgent.
- *
- * @hide
- */
- public String fullBackupAgentName;
-
- /**
* Value for {@link #flags}: if set, this application is installed in the
* device's system image.
*/
@@ -555,7 +546,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
dest.writeInt(installLocation);
dest.writeString(manageSpaceActivityName);
dest.writeString(backupAgentName);
- dest.writeString(fullBackupAgentName);
dest.writeInt(descriptionRes);
}
@@ -593,7 +583,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
installLocation = source.readInt();
manageSpaceActivityName = source.readString();
backupAgentName = source.readString();
- fullBackupAgentName = source.readString();
descriptionRes = source.readInt();
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 208869b6c2fd..53d6bb17a551 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1517,17 +1517,6 @@ public class PackageParser {
}
}
- // fullBackupAgent is explicitly handled even if allowBackup is false
- name = sa.getNonConfigurationString(
- com.android.internal.R.styleable.AndroidManifestApplication_fullBackupAgent, 0);
- if (name != null) {
- ai.fullBackupAgentName = buildClassName(pkgName, name, outError);
- if (false) {
- Log.v(TAG, "android:fullBackupAgent=" + ai.fullBackupAgentName
- + " from " + pkgName + "+" + name);
- }
- }
-
TypedValue v = sa.peekValue(
com.android.internal.R.styleable.AndroidManifestApplication_label);
if (v != null && (ai.labelRes=v.resourceId) == 0) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1a320608efae..49eaf1912617 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1418,7 +1418,6 @@
android:label="@string/android_system_label"
android:allowClearUserData="false"
android:backupAgent="com.android.server.SystemBackupAgent"
- android:fullBackupAgent="com.android.server.SystemBackupAgent"
android:killAfterRestore="false"
android:icon="@drawable/ic_launcher_android">
<activity android:name="com.android.internal.app.ChooserActivity"
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 03b332ee75b6..dd16bd072df6 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -696,13 +696,6 @@
<p>The default value of this attribute is <code>false</code>. -->
<attr name="restoreAnyVersion" format="boolean" />
- <!-- The agent to use for a *full* backup of the package. Only system applications
- can use this to override the ordinary FullBackupAgent with a custom implementation.
- It's needed strictly for packages with strongly device-specific data, such as the
- Settings provider.
- -->
- <attr name="fullBackupAgent" format="string" />
-
<!-- The default install location defined by an application. -->
<attr name="installLocation">
<!-- Let the system decide ideal install location -->
@@ -800,7 +793,6 @@
<attr name="killAfterRestore" />
<attr name="restoreNeedsApplication" />
<attr name="restoreAnyVersion" />
- <attr name="fullBackupAgent" />
<attr name="neverEncrypt" />
<!-- Request that your application's processes be created with
a large Dalvik heap. This applies to <em>all</em> processes
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 54e484ee95de..20f5e7cf2eed 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1725,7 +1725,6 @@
<public type="attr" name="layoutDirection" />
- <public type="attr" name="fullBackupAgent" />
<public type="attr" name="suggestionsEnabled" />
<public type="attr" name="rowCount" />
@@ -1737,7 +1736,6 @@
<public type="attr" name="layout_row" />
<public type="attr" name="layout_rowSpan" />
-
<public type="attr" name="layout_columnSpan" />
<public type="attr" name="layout_widthSpec" />
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index e5f52e24e807..dd0d064ceeef 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -6,7 +6,6 @@
android:label="@string/app_label"
android:process="system"
android:backupAgent="SettingsBackupAgent"
- android:fullBackupAgent="SettingsBackupAgent"
android:killAfterRestore="false"
android:icon="@drawable/ic_launcher_settings">
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 946960122565..3a7a6e153803 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -36,7 +36,7 @@ import java.util.zip.CRC32;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupAgentHelper;
-import android.app.backup.FullBackup;
+import android.app.backup.FullBackupDataOutput;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -132,58 +132,22 @@ public class SettingsBackupAgent extends BackupAgentHelper {
byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
byte[] wifiConfigData = getFileData(mWifiConfigFile);
- // This same agent class is used for both full and incremental backups. A full
- // backup is flagged by a 'null' oldState argument. In the case of a full backup,
- // the output is structured as tarfile contents.
- if (oldState != null) {
- long[] stateChecksums = readOldChecksums(oldState);
-
- stateChecksums[STATE_SYSTEM] =
- writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
- stateChecksums[STATE_SECURE] =
- writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
- stateChecksums[STATE_LOCALE] =
- writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
- stateChecksums[STATE_WIFI_SUPPLICANT] =
- writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
- wifiSupplicantData, data);
- stateChecksums[STATE_WIFI_CONFIG] =
- writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
- data);
-
- writeNewChecksums(stateChecksums, newState);
- } else {
- // Write the data to the staging file, then emit that as our tarfile
- // representation of the backed-up settings.
- String root = getFilesDir().getAbsolutePath();
- File stage = new File(root, STAGE_FILE);
- try {
- FileOutputStream filestream = new FileOutputStream(stage);
- BufferedOutputStream bufstream = new BufferedOutputStream(filestream);
- DataOutputStream out = new DataOutputStream(bufstream);
-
- out.writeInt(FULL_BACKUP_VERSION);
-
- out.writeInt(systemSettingsData.length);
- out.write(systemSettingsData);
- out.writeInt(secureSettingsData.length);
- out.write(secureSettingsData);
- out.writeInt(locale.length);
- out.write(locale);
- out.writeInt(wifiSupplicantData.length);
- out.write(wifiSupplicantData);
- out.writeInt(wifiConfigData.length);
- out.write(wifiConfigData);
-
- out.flush(); // also flushes downstream
-
- // now we're set to emit the tar stream
- FullBackup.backupToTar(getPackageName(), FullBackup.DATA_TREE_TOKEN, null,
- root, stage.getAbsolutePath(), data);
- } finally {
- stage.delete();
- }
- }
+ long[] stateChecksums = readOldChecksums(oldState);
+
+ stateChecksums[STATE_SYSTEM] =
+ writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
+ stateChecksums[STATE_SECURE] =
+ writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
+ stateChecksums[STATE_LOCALE] =
+ writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
+ stateChecksums[STATE_WIFI_SUPPLICANT] =
+ writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
+ wifiSupplicantData, data);
+ stateChecksums[STATE_WIFI_CONFIG] =
+ writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
+ data);
+
+ writeNewChecksums(stateChecksums, newState);
}
@Override
@@ -221,6 +185,45 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
@Override
+ public void onFullBackup(FullBackupDataOutput data) throws IOException {
+ byte[] systemSettingsData = getSystemSettings();
+ byte[] secureSettingsData = getSecureSettings();
+ byte[] locale = mSettingsHelper.getLocaleData();
+ byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
+ byte[] wifiConfigData = getFileData(mWifiConfigFile);
+
+ // Write the data to the staging file, then emit that as our tarfile
+ // representation of the backed-up settings.
+ String root = getFilesDir().getAbsolutePath();
+ File stage = new File(root, STAGE_FILE);
+ try {
+ FileOutputStream filestream = new FileOutputStream(stage);
+ BufferedOutputStream bufstream = new BufferedOutputStream(filestream);
+ DataOutputStream out = new DataOutputStream(bufstream);
+
+ out.writeInt(FULL_BACKUP_VERSION);
+
+ out.writeInt(systemSettingsData.length);
+ out.write(systemSettingsData);
+ out.writeInt(secureSettingsData.length);
+ out.write(secureSettingsData);
+ out.writeInt(locale.length);
+ out.write(locale);
+ out.writeInt(wifiSupplicantData.length);
+ out.write(wifiSupplicantData);
+ out.writeInt(wifiConfigData.length);
+ out.write(wifiConfigData);
+
+ out.flush(); // also flushes downstream
+
+ // now we're set to emit the tar stream
+ fullBackupFile(stage, data);
+ } finally {
+ stage.delete();
+ }
+ }
+
+ @Override
public void onRestoreFile(ParcelFileDescriptor data, long size,
int type, String domain, String relpath, long mode, long mtime)
throws IOException {
diff --git a/packages/SharedStorageBackup/AndroidManifest.xml b/packages/SharedStorageBackup/AndroidManifest.xml
index 258059c54fce..39c36f1b2ec6 100644
--- a/packages/SharedStorageBackup/AndroidManifest.xml
+++ b/packages/SharedStorageBackup/AndroidManifest.xml
@@ -23,7 +23,7 @@
<application android:allowClearUserData="false"
android:permission="android.permission.CONFIRM_FULL_BACKUP"
- android:fullBackupAgent=".SharedStorageAgent"
+ android:backupAgent=".SharedStorageAgent"
android:allowBackup="false" >
</application>
</manifest>
diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
index b02ca2e761ec..6c677b878501 100644
--- a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
+++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
@@ -1,9 +1,10 @@
package com.android.sharedstoragebackup;
-import android.app.backup.FullBackup;
import android.app.backup.FullBackupAgent;
+import android.app.backup.FullBackup;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
+import android.app.backup.FullBackupDataOutput;
import android.content.Context;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
@@ -30,9 +31,11 @@ public class SharedStorageAgent extends FullBackupAgent {
}
}
+ /**
+ * Full backup of the shared-storage filesystem
+ */
@Override
- public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
- ParcelFileDescriptor newState) throws IOException {
+ public void onFullBackup(FullBackupDataOutput output) throws IOException {
// If there are shared-storage volumes available, run the inherited directory-
// hierarchy backup process on them. By convention in the Storage Manager, the
// "primary" shared storage volume is first in the list.
@@ -43,20 +46,12 @@ public class SharedStorageAgent extends FullBackupAgent {
// shared/N/path/to/file
// The restore will then extract to the given volume
String domain = FullBackup.SHARED_PREFIX + i;
- processTree(null, domain, v.getPath(), null, data);
+ fullBackupFileTree(null, domain, v.getPath(), null, output);
}
}
}
/**
- * Incremental onRestore() implementation is not used.
- */
- @Override
- public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
- throws IOException {
- }
-
- /**
* Full restore of one file to shared storage
*/
@Override
@@ -88,6 +83,6 @@ public class SharedStorageAgent extends FullBackupAgent {
Slog.e(TAG, "Skipping data with malformed path " + relpath);
}
- FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, false);
+ FullBackup.restoreFile(data, size, type, -1, mtime, outFile);
}
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 3aa1239c8df9..6afccec4df04 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -23,6 +23,7 @@ import android.app.IActivityManager;
import android.app.IApplicationThread;
import android.app.IBackupAgent;
import android.app.PendingIntent;
+import android.app.backup.BackupAgent;
import android.app.backup.BackupDataOutput;
import android.app.backup.FullBackup;
import android.app.backup.RestoreSet;
@@ -64,6 +65,7 @@ import android.os.SystemClock;
import android.os.WorkSource;
import android.provider.Settings;
import android.util.EventLog;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -1587,8 +1589,7 @@ class BackupManagerService extends IBackupManager.Stub {
// Initiate the target's backup pass
prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL);
- agent.doBackup(savedState, backupData, newState, false,
- token, mBackupManagerBinder);
+ agent.doBackup(savedState, backupData, newState, token, mBackupManagerBinder);
boolean success = waitUntilOperationComplete(token);
if (!success) {
@@ -1764,30 +1765,31 @@ class BackupManagerService extends IBackupManager.Stub {
if (agent != null) {
try {
ApplicationInfo app = pkg.applicationInfo;
- boolean sendApk = mIncludeApks
+ final boolean sendApk = mIncludeApks
&& ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0)
&& ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
(app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
sendOnBackupPackage(pkg.packageName);
- {
- BackupDataOutput output = new BackupDataOutput(
- mOutputFile.getFileDescriptor());
+ BackupDataOutput output = new BackupDataOutput(
+ mOutputFile.getFileDescriptor());
- if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName);
- writeAppManifest(pkg, mManifestFile, sendApk);
- FullBackup.backupToTar(pkg.packageName, null, null,
- mFilesDir.getAbsolutePath(),
- mManifestFile.getAbsolutePath(),
- output);
+ if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName);
+ writeAppManifest(pkg, mManifestFile, sendApk);
+ FullBackup.backupToTar(pkg.packageName, null, null,
+ mFilesDir.getAbsolutePath(),
+ mManifestFile.getAbsolutePath(),
+ output);
+
+ if (sendApk) {
+ writeApkToBackup(pkg, output);
}
- if (DEBUG) Slog.d(TAG, "Calling doBackup()");
+ if (DEBUG) Slog.d(TAG, "Calling doFullBackup()");
final int token = generateToken();
prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL);
- agent.doBackup(null, mOutputFile, null, sendApk,
- token, mBackupManagerBinder);
+ agent.doFullBackup(mOutputFile, token, mBackupManagerBinder);
if (!waitUntilOperationComplete(token)) {
Slog.e(TAG, "Full backup failed on package " + pkg.packageName);
} else {
@@ -1802,6 +1804,29 @@ class BackupManagerService extends IBackupManager.Stub {
tearDown(pkg);
}
+ private void writeApkToBackup(PackageInfo pkg, BackupDataOutput output) {
+ // Forward-locked apps, system-bundled .apks, etc are filtered out before we get here
+ final String appSourceDir = pkg.applicationInfo.sourceDir;
+ final String apkDir = new File(appSourceDir).getParent();
+ FullBackup.backupToTar(pkg.packageName, FullBackup.APK_TREE_TOKEN, null,
+ apkDir, appSourceDir, output);
+
+ // Save associated .obb content if it exists and we did save the apk
+ // check for .obb and save those too
+ final File obbDir = Environment.getExternalStorageAppObbDirectory(pkg.packageName);
+ if (obbDir != null) {
+ if (DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath());
+ File[] obbFiles = obbDir.listFiles();
+ if (obbFiles != null) {
+ final String obbDirName = obbDir.getAbsolutePath();
+ for (File obb : obbFiles) {
+ FullBackup.backupToTar(pkg.packageName, FullBackup.OBB_TREE_TOKEN, null,
+ obbDirName, obb.getAbsolutePath(), output);
+ }
+ }
+ }
+ }
+
private void backupSharedStorage() throws RemoteException {
PackageInfo pkg = null;
try {
@@ -1813,7 +1838,7 @@ class BackupManagerService extends IBackupManager.Stub {
final int token = generateToken();
prepareOperationTimeout(token, TIMEOUT_SHARED_BACKUP_INTERVAL);
- agent.doBackup(null, mOutputFile, null, false, token, mBackupManagerBinder);
+ agent.doFullBackup(mOutputFile, token, mBackupManagerBinder);
if (!waitUntilOperationComplete(token)) {
Slog.e(TAG, "Full backup failed on shared storage");
} else {
@@ -1933,7 +1958,7 @@ class BackupManagerService extends IBackupManager.Stub {
static class FileMetadata {
String packageName; // name of the owning app
String installerPackageName; // name of the market-type app that installed the owner
- int type; // e.g. FullBackup.TYPE_DIRECTORY
+ int type; // e.g. BackupAgent.TYPE_DIRECTORY
String domain; // e.g. FullBackup.DATABASE_TREE_TOKEN
String path; // subpath within the semantic domain
long mode; // e.g. 0666 (actually int)
@@ -2182,15 +2207,15 @@ class BackupManagerService extends IBackupManager.Stub {
// If we haven't sent any data to this app yet, we probably
// need to clear it first. Check that.
if (!mClearedPackages.contains(pkg)) {
- // apps with their own full backup agents are
+ // apps with their own backup agents are
// responsible for coherently managing a full
// restore.
- if (mTargetApp.fullBackupAgentName == null) {
+ if (mTargetApp.backupAgentName == null) {
if (DEBUG) Slog.d(TAG, "Clearing app data preparatory to full restore");
clearApplicationDataSynchronous(pkg);
} else {
- if (DEBUG) Slog.d(TAG, "full backup agent ("
- + mTargetApp.fullBackupAgentName + ") => no clear");
+ if (DEBUG) Slog.d(TAG, "backup agent ("
+ + mTargetApp.backupAgentName + ") => no clear");
}
mClearedPackages.add(pkg);
} else {
@@ -2686,7 +2711,7 @@ class BackupManagerService extends IBackupManager.Stub {
StringBuilder b = new StringBuilder(128);
// mode string
- b.append((info.type == FullBackup.TYPE_DIRECTORY) ? 'd' : '-');
+ b.append((info.type == BackupAgent.TYPE_DIRECTORY) ? 'd' : '-');
b.append(((info.mode & 0400) != 0) ? 'r' : '-');
b.append(((info.mode & 0200) != 0) ? 'w' : '-');
b.append(((info.mode & 0100) != 0) ? 'x' : '-');
@@ -2746,9 +2771,9 @@ class BackupManagerService extends IBackupManager.Stub {
}
switch (typeChar) {
- case '0': info.type = FullBackup.TYPE_FILE; break;
+ case '0': info.type = BackupAgent.TYPE_FILE; break;
case '5': {
- info.type = FullBackup.TYPE_DIRECTORY;
+ info.type = BackupAgent.TYPE_DIRECTORY;
if (info.size != 0) {
Slog.w(TAG, "Directory entry with nonzero size in header");
info.size = 0;
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
index 08c66996128e..950f3b68f6d5 100644
--- a/services/java/com/android/server/SystemBackupAgent.java
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -138,7 +138,7 @@ public class SystemBackupAgent extends BackupAgentHelper {
if (outFile == null) {
Slog.w(TAG, "Skipping unrecognized system file: [ " + domain + " : " + path + " ]");
}
- FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, true);
+ FullBackup.restoreFile(data, size, type, mode, mtime, outFile);
if (restoredWallpaper) {
WallpaperManagerService wallpaper =