This page shows you how to test the cloud backups and the device-to-device (D2D)
transfer process for your app. It is important to test both of these with each
major release of your app to help ensure that your users can continue to use your app
on a new device. While both backup and transfer are similar, there are important
differences between the two in Android 12 (API level 31) and higher---most
notably that transfer has a much larger data size limit of 2 GB, compared with
25 MB for cloud backup.

This guide shows you how you can test both cloud backup and restore and D2D
transfer efficiently throughout the development cycle.

## How testing backups works

This section describes various pieces in the Android backup framework and how
they interact with apps that support Auto Backup and key-value backup. During
the app development phase, most of the inner working of the framework are
abstracted away, so you don't need to know this information. However, during
the testing phase, an understanding of these concepts becomes more important.

The following diagram illustrates how data flows during cloud backup and
restore. For testing purposes, the same device can be used for cloud backup and
restore.

![Backup Framework Data Flow](https://developer.android.com/static/identity/data/images/remote_backup.png)

The following diagram illustrates how the data flows during a D2D transfer:

![Transfer Framework Data Flow](https://developer.android.com/static/identity/data/images/device_to_device_transfer.png)

Unlike cloud backup and restore testing, D2D testing requires a source device
and a target device to copy from and to.

The *Backup Manager Service* is an Android system service that orchestrates and
initiates backup and restore operations. The service is accessible through the
[`Backup Manager`](https://developer.android.com/reference/android/app/backup/BackupManager) API.

During
a backup operation, the service queries your app for backup data, then hands it
to the *backup transport*, which then archives the data to the cloud. During a
restore operation, the Backup Manager Service retrieves the backup data from the
backup transport and restores the data to the device. For a D2D transfer, the
Backup Manager Service queries your app for backup data and passes it directly
to the Backup Manager Service on the new device, which loads it in to your app.

*Backup Transports* are Android components that are responsible for storing and
retrieving your app data. An Android-powered device can have zero or more backup
transports, but only one of those transports can be marked active. The available
backup transports differ from device to device, due to customizations by
device manufacturers and service providers, but most Google Play-enabled
devices ship with the following transports:

- **GMS Transport:** the active cloud backup transport on most devices, part of [Google Mobile Services](https://www.android.com/gms/). This transport stores data in the Android Backup Service.
- **D2D Transport:** this transport is used in D2D migration to transfer data directly from one device to another.

## Tools

To test your backup and restore operations, you need to know a bit about the
following tools.

- [`adb`](https://developer.android.com/studio/command-line/adb): to run commands on the device or emulator.
- [`bmgr`](https://developer.android.com/studio/command-line/bmgr): to perform various backup and restore operations.
- [`logcat`](https://developer.android.com/studio/command-line/logcat): to see the output of backup and restore operations.

## Test cloud backup

Cloud backup and restore can be performed using a single device by following the
steps in this section.

### Prepare your device or emulator for cloud backups

Prepare your device or emulator for backup testing by working through the
following checklist:

1. For Auto Backup, check that you are using a device or emulator running Android 6.0 (API level 23) or higher.
2. For key-value backup, check that you are using a device or emulator running Android 2.2 (API level 8) or higher.
3. You must have internet access to test cloud backup.
4. Log into the device with a Google Account and set it as the backup account in **Settings -\> Google -\> Backup**.

To test cloud backup, trigger a cloud backup, then uninstall and reinstall the
app. To make these steps repeatable, you can use the following script,
`test_cloud_backup.sh`, which backs up your app, downloads the APK locally,
uninstalls it, and reinstalls the APK:  

    #!/bin/bash -eu
    : "${1?"Usage: $0 package name"}"

    # Initialize and create a backup
    adb shell bmgr enable true
    adb shell bmgr transport com.android.localtransport/.LocalTransport | grep -q "Selected transport" || (echo "Error: error selecting local transport"; exit 1)
    adb shell settings put secure backup_local_transport_parameters 'is_encrypted=true'
    adb shell bmgr backupnow "$1" | grep -F "Package $1 with result: Success" || (echo "Backup failed"; exit 1)

    # Uninstall and reinstall the app to clear the data and trigger a restore
    apk_path_list=$(adb shell pm path "$1")
    OIFS=$IFS
    IFS=$'\n'
    apk_number=0
    for apk_line in $apk_path_list
    do
        (( ++apk_number ))
        apk_path=${apk_line:8:1000}
        adb pull "$apk_path" "myapk${apk_number}.apk"
    done
    IFS=$OIFS
    adb shell pm uninstall --user 0 "$1"
    apks=$(seq -f 'myapk%.f.apk' 1 $apk_number)
    adb install-multiple -t --user 0 $apks

    # Clean up
    adb shell bmgr transport com.google.android.gms/.backup.BackupTransportService
    rm $apks

    echo "Done"

### Test steps

1. Open your app, log in, and modify all settings.
2. Run the script, passing in your package name, such as `test_cloud_backup.sh com.example.myapp`
3. Re-open the app and validate that it works correctly, with all data retained.

You don't want your users to need to log in, and all their settings, progress
and app data must be as they were before. If your test results don't meet these
criteria, make sure you have configured backups
correctly, without omitting key pieces of data, and that you are also handling
the recreation of any cached data that you excluded from the backup. Repeat
steps 1-3 for each test iteration.

## Test D2D transfer

The most comprehensive way to test D2D transfer is by transferring your entire
phone contents to a new, factory-reset device and validating that it works
correctly. However, this can be inconvenient and time consuming if you need to repeat the
process multiple times. These steps show you how to simulate a transfer with a single
device without repeatedly performing a factory reset on the device.

### Prepare your device for D2D testing

To test D2D transfer on a single device, prepare it as follows:

1. Your device must be running Android 12 (API level 31) or higher.
2. To test the latest version of D2D, target Android 12 (API level 31) or higher in your app.
3. Create the following script, `test_d2d.sh`, to support repetition of the test:

    #!/bin/bash -eu
    : "${1?"Usage: $0 package name"}"

    # Initialize and create a backup
    adb shell bmgr enable true
    adb shell settings put secure backup_enable_d2d_test_mode 1
    adb shell bmgr transport com.google.android.gms/.backup.migrate.service.D2dTransport
    adb shell bmgr init com.google.android.gms/.backup.migrate.service.D2dTransport
    adb shell bmgr list transports | grep -q -F "  * com.google.android.gms/.backup.migrate.service.D2dTransport" || (echo "Failed to select and initialize backup transport"; exit 1)
    adb shell bmgr backupnow "$1" | grep -F "Package $1 with result: Success" || (echo "Backup failed"; exit 1)

    # Uninstall and reinstall the app to clear the data and trigger a restore
    apk_path_list=$(adb shell pm path "$1")
    OIFS=$IFS
    IFS=$'\n'
    apk_number=0
    for apk_line in $apk_path_list
    do
        (( ++apk_number ))
        apk_path=${apk_line:8:1000}
        adb pull "$apk_path" "myapk${apk_number}.apk"
    done
    IFS=$OIFS
    adb shell pm uninstall --user 0 "$1"
    adb shell bmgr transport com.google.android.gms/.backup.BackupTransportService
    apks=$(seq -f 'myapk%.f.apk' 1 $apk_number)
    adb install-multiple -t --user 0 $apks

    # Clean up
    adb shell bmgr init com.google.android.gms/.backup.migrate.service.D2dTransport
    adb shell settings put secure backup_enable_d2d_test_mode 0
    adb shell bmgr transport com.google.android.gms/.backup.BackupTransportService
    rm $apks

    echo "Done"

### Test steps

1. Install the app you want to test on the device.
2. Open your app, log in, and modify your app's settings.
3. Run the script on your device, passing in your package name, such as `test_d2d.sh com.example.myapp`.
4. When the script is complete, open the app on the device and validate that it works correctly, with all data retained.

You don't want your users to need to log in, and all their settings, progress
and app data must appear as they did prior to running the script.
If your test results don't meet these criteria, make sure you have configured
transfer correctly, without omitting key
pieces of data, and that you are also handling the recreation of any cached data
that you excluded from the transfer. Repeat steps 2-4 for each test iteration.

## Troubleshoot backup and restore

This section helps you troubleshoot some common issues.

**Transport quota exceeded**

The following messages in Logcat indicate that your app has exceeded the
transport quota:  

    I/PFTBT: Transport rejected backup of <PACKAGE>, skipping

    --- or ---

    I/PFTBT: Transport quota exceeded for package: <PACKAGE>

Reduce the amount of backup data and try again.
For example, verify that you are caching data only in the cache directory of
your app. The cache directory isn't included in backups.

**Full backup not possible**

The following message in Logcat indicates that the full backup operation failed
because no key-value backup operation has yet occurred on the device:  

    I/BackupManagerService: Full backup not currently possible -- key/value backup
    not yet run?

Trigger a key-value backup with the command `bmgr run`, and then try again.

**Timeout waiting for agent**

The following message in Logcat indicates that your app is taking more than 10
seconds to launch for backup:  

    12-05 18:59:02.033  1910  2251 D BackupManagerService:
        awaiting agent for ApplicationInfo{5c7cde0 com.your.app.package}
    12-05 18:59:12.117  1910  2251 W BackupManagerService:
        Timeout waiting for agent ApplicationInfo{5c7cde0 com.your.app.package}
    12-05 18:59:12.117  1910  2251 W BackupManagerService:
        Can't find backup agent for com.your.app.package

Notice the timestamp difference in the log output. This error typically occurs
when your app makes use of a multidex configuration without ProGuard.

**Uninitialized backup account**

The following messages in Logcat indicate that the backup was halted because
the backup dataset was not initialized:  

    01-31 14:32:45.698 17280 17292 I Backup: [GmsBackupTransport] Try to backup for
    an uninitialized backup account.
    01-31 14:32:45.699  1043 18255 W PFTBT: Transport failed; aborting backup: -1001
    01-31 14:32:45.699  1043 18255 I PFTBT: Full backup completed with status: -1000

Run the
backup manager with the command `adb shell bmgr run`, and then try to
perform the backup again.

**App methods not called**

Because Auto Backup launches your app with a base class of
[`Application`](https://developer.android.com/reference/android/app/Application), your app's setup methods
might not be called. Auto Backup doesn't launch any of your app's activities,
either, so you might see errors if your app does setup in an activity. To learn
more, read
[Implement BackupAgent](https://developer.android.com/guide/topics/data/autobackup#ImplementingBackupAgent).

In contrast, key-value backup launches your app with any `Application`
subclass you declare in your app manifest file.

**No data to back up**

The following messages in Logcat indicate that your app has no data to back up:  

    I Backup  : [FullBackupSession] Package com.your.app.package doesn't have any backup data.

    --- or ---

    I Backup  : [D2dTransport] Package com.your.app.package doesn't have any backup data.

If you [implemented your own
`BackupAgent`](https://developer.android.com/guide/topics/data/autobackup#ImplementingBackupAgent), this
likely means you have not added any data or files to the backup.