CTS test for 'fullBackupOnly' manifest attribute
Uses 3 different versions of the same app that differ only by
'fullBackupOnly' value and the presence/absence of the backup agent.
Tests the following scenarios:
1. App that doesn't have fullBackupOnly (same as fullBackupOnly=false by
default) and has a backup agent will get key/value backup.
We check that key/value data was restored after reinstall and dolly data was not.
2. App that doesn't have fullBackupOnly (same as fullBackupOnly=false by
default) and has no backup agent will get Dolly backup.
We check that key/value data was not restored after reinstall and dolly data was.
3. App that has fullBackupOnly=true and has a backup agent will only
get Dolly backup.
We check that key/value data was not restored after reinstall and dolly data was.
The flow of the tests is the following:
1. Install the app
2. Generate files in data folder of the app, including a file in
no_backup folder. The file in no_backup folder is used for key/value backup by
the backup agent of the app.
3. Run 'bmgr backupnow'. Depending on the manifest of the app we expect
either Dolly or Key/value backup to be performed.
4. Uninstall and reinstall the app.
5. Check that the correct files were restored depending on the manifest:
- Files in the app's data folder for Dolly backup
- Only file in no_backup folder for key/value.
Test: cts-tradefed run cts-dev -m CtsBackupHostTestCases -t android.cts.backup.FullBackupOnlyHostSideTest
Bug: 38108587
Change-Id: If29577a5209fc77cebebe23dc879c51ab4be5e65
diff --git a/hostsidetests/backup/FullBackupOnly/Android.mk b/hostsidetests/backup/FullBackupOnly/Android.mk
new file mode 100644
index 0000000..521ac4d
--- /dev/null
+++ b/hostsidetests/backup/FullBackupOnly/Android.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include $(call all-subdir-makefiles)
diff --git a/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseNoAgentApp/Android.mk b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseNoAgentApp/Android.mk
new file mode 100644
index 0000000..5cce7a4
--- /dev/null
+++ b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseNoAgentApp/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := FullBackupOnlyFalseNoAgentApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseNoAgentApp/AndroidManifest.xml b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseNoAgentApp/AndroidManifest.xml
new file mode 100644
index 0000000..c00671f
--- /dev/null
+++ b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseNoAgentApp/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.cts.backup.fullbackuponlyapp">
+
+ <application>
+
+ <uses-library android:name="android.test.runner" />
+
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.cts.backup.fullbackuponlyapp" />
+
+</manifest>
diff --git a/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseWithAgentApp/Android.mk b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseWithAgentApp/Android.mk
new file mode 100644
index 0000000..3224b98
--- /dev/null
+++ b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseWithAgentApp/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := FullBackupOnlyFalseWithAgentApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseWithAgentApp/AndroidManifest.xml b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseWithAgentApp/AndroidManifest.xml
new file mode 100644
index 0000000..03555d4
--- /dev/null
+++ b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyFalseWithAgentApp/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.cts.backup.fullbackuponlyapp">
+
+ <application
+ android:backupAgent=".FullBackupOnlyBackupAgent">
+
+ <uses-library android:name="android.test.runner" />
+
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.cts.backup.fullbackuponlyapp" />
+
+</manifest>
diff --git a/hostsidetests/backup/FullBackupOnly/FullBackupOnlyTrueWithAgentApp/Android.mk b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyTrueWithAgentApp/Android.mk
new file mode 100644
index 0000000..2f0eae8
--- /dev/null
+++ b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyTrueWithAgentApp/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := FullBackupOnlyTrueWithAgentApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/backup/FullBackupOnly/FullBackupOnlyTrueWithAgentApp/AndroidManifest.xml b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyTrueWithAgentApp/AndroidManifest.xml
new file mode 100644
index 0000000..9b90592
--- /dev/null
+++ b/hostsidetests/backup/FullBackupOnly/FullBackupOnlyTrueWithAgentApp/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.cts.backup.fullbackuponlyapp">
+
+ <application
+ android:backupAgent=".FullBackupOnlyBackupAgent"
+ android:fullBackupOnly="true">
+
+ <uses-library android:name="android.test.runner" />
+
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.cts.backup.fullbackuponlyapp" />
+
+</manifest>
diff --git a/hostsidetests/backup/FullBackupOnly/src/FullBackupOnlyBackupAgent.java b/hostsidetests/backup/FullBackupOnly/src/FullBackupOnlyBackupAgent.java
new file mode 100644
index 0000000..f14ce24
--- /dev/null
+++ b/hostsidetests/backup/FullBackupOnly/src/FullBackupOnlyBackupAgent.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.cts.backup.fullbackuponlyapp;
+
+import android.app.backup.BackupAgent;
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * BackupAgent for test apps in {@link android.cts.backup.fullbackuponlyapp} package.
+ * Performs backup/restore of the file provided by {@link FullBackupOnlyTest}.
+ *
+ * Implementation of key/value backup methods is based on the examples from
+ * https://developer.android.com/guide/topics/data/keyvaluebackup.html
+ */
+public class FullBackupOnlyBackupAgent extends BackupAgent {
+ private static final String TAG = "FullBackupOnlyBA";
+
+ private static final String BACKUP_KEY = "full_backup_only_key";
+ private static final int DEFAULT_VALUE = -1;
+
+ /** Get the value saved in the shared preference and back it up. */
+ @Override
+ public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState) throws IOException {
+ Log.i(TAG, "onBackup");
+
+ File fileToBackup = FullBackupOnlyTest.getKeyValueBackupFile(this);
+ byte[] buffer = readFileToBytes(fileToBackup);
+
+ // Send the data to the Backup Manager via the BackupDataOutput
+ int len = buffer.length;
+ data.writeEntityHeader(BACKUP_KEY, len);
+ data.writeEntityData(buffer, len);
+ }
+
+ /** Get the value from backup and save it in the shared preference. */
+ @Override
+ public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+ throws IOException {
+ Log.i(TAG, "onRestore");
+ int value = DEFAULT_VALUE;
+
+ // There should be only one entity, but the safest
+ // way to consume it is using a while loop
+ while (data.readNextHeader()) {
+ String key = data.getKey();
+ int dataSize = data.getDataSize();
+
+ // If the key is ours (for saving top score). Note this key was used when
+ // we wrote the backup entity header
+ if (BACKUP_KEY.equals(key)) {
+ // Copy data from BackupDataInput and write it into the file.
+ byte[] dataBuf = new byte[dataSize];
+ data.readEntityData(dataBuf, 0, dataSize);
+
+ File fileToRestore = FullBackupOnlyTest.getKeyValueBackupFile(this);
+
+ try (BufferedOutputStream bos = new BufferedOutputStream(
+ new FileOutputStream(fileToRestore))) {
+ bos.write(dataBuf, 0, dataBuf.length);
+ }
+ } else {
+ // We don't know this entity key. Shouldn't happen.
+ throw new RuntimeException("Unexpected key in the backup data");
+ }
+ }
+
+ // Finally, write to the state blob (newState) that describes the restored data
+ FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
+ DataOutputStream out = new DataOutputStream(outstream);
+ out.writeInt(value);
+ }
+
+
+ private byte[] readFileToBytes(File file) {
+ int size = (int) file.length();
+ byte[] bytes = new byte[size];
+ try {
+ BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
+ buf.read(bytes, 0, bytes.length);
+ buf.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Key/value file not found", e);
+ } catch (IOException e) {
+ throw new RuntimeException("Error reading key/value file", e);
+ }
+ return bytes;
+ }
+}
diff --git a/hostsidetests/backup/FullBackupOnly/src/FullBackupOnlyTest.java b/hostsidetests/backup/FullBackupOnly/src/FullBackupOnlyTest.java
new file mode 100644
index 0000000..17a7e2c
--- /dev/null
+++ b/hostsidetests/backup/FullBackupOnly/src/FullBackupOnlyTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.cts.backup.fullbackuponlyapp;
+
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Random;
+
+/**
+ * Device side routines to be invoked by the host side FullBackupOnlyHostSideTest. These
+ * are not designed to be called in any other way, as they rely on state set up by the host side
+ * test.
+ */
+@RunWith(AndroidJUnit4.class)
+public class FullBackupOnlyTest {
+ private static final String TAG = "FullBackupOnlyTest";
+
+ private static final int FILE_SIZE_BYTES = 1024 * 1024;
+
+ private File mKeyValueBackupFile;
+ private File mDoBackupFile;
+ private File mDoBackupFile2;
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ Log.i(TAG, "set up");
+ mContext = getTargetContext();
+ setupFiles();
+ }
+
+ private void setupFiles() {
+ mKeyValueBackupFile = getKeyValueBackupFile(mContext);
+
+ // Files to be backed up with Dolly
+ File filesDir = mContext.getFilesDir();
+ File normalFolder = new File(filesDir, "normal_folder");
+
+ mDoBackupFile = new File(filesDir, "file_to_backup");
+ mDoBackupFile2 = new File(normalFolder, "file_to_backup2");
+ }
+
+ @Test
+ public void createFiles() throws Exception {
+ // Make sure the data does not exist from before
+ deleteAllFiles();
+ assertNoFilesExist();
+
+ // Create test data
+ generateFiles();
+ assertAllFilesExist();
+
+ Log.d(TAG, "Test files created: \n"
+ + mKeyValueBackupFile.getAbsolutePath() + "\n"
+ + mDoBackupFile.getAbsolutePath() + "\n"
+ + mDoBackupFile2.getAbsolutePath());
+ }
+
+ @Test
+ public void checkKeyValueFileDoesntExist() throws Exception {
+ assertKeyValueFileDoesntExist();
+ }
+
+ @Test
+ public void checkKeyValueFileExists() throws Exception {
+ assertKeyValueFileExists();
+ }
+
+ @Test
+ public void checkDollyFilesExist() throws Exception {
+ assertDollyFilesExist();
+ }
+
+ @Test
+ public void checkDollyFilesDontExist() throws Exception {
+ assertDollyFilesDontExist();
+ }
+
+ protected static File getKeyValueBackupFile(Context context) {
+ // Files in the 'no_backup' directory are not backed up with Dolly.
+ // We're going to use it to store a file the contents of which are backed up via key/value.
+ File noBackupDir = context.getNoBackupFilesDir();
+ return new File(noBackupDir, "key_value_backup_file");
+ }
+
+ private void generateFiles() {
+ try {
+ // Add data to all the files we created
+ addData(mKeyValueBackupFile);
+ addData(mDoBackupFile);
+ addData(mDoBackupFile2);
+ Log.d(TAG, "Files generated!");
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to generate files", e);
+ }
+ }
+
+ private void deleteAllFiles() {
+ mKeyValueBackupFile.delete();
+ mDoBackupFile.delete();
+ mDoBackupFile2.delete();
+ Log.d(TAG, "Files deleted!");
+ }
+
+ private void addData(File file) throws IOException {
+ file.getParentFile().mkdirs();
+ byte[] bytes = new byte[FILE_SIZE_BYTES];
+ new Random().nextBytes(bytes);
+
+ try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
+ bos.write(bytes, 0, bytes.length);
+ }
+ }
+
+ private void assertAllFilesExist() {
+ assertKeyValueFileExists();
+ assertDollyFilesExist();
+ }
+
+ private void assertNoFilesExist() {
+ assertKeyValueFileDoesntExist();
+ assertDollyFilesDontExist();
+ }
+
+ private void assertKeyValueFileExists() {
+ assertTrue("Key/value file did not exist!", mKeyValueBackupFile.exists());
+ }
+
+ private void assertKeyValueFileDoesntExist() {
+ assertFalse("Key/value file did exist!", mKeyValueBackupFile.exists());
+ }
+
+ private void assertDollyFilesExist() {
+ assertTrue("File in 'files' did not exist!", mDoBackupFile.exists());
+ assertTrue("File in folder inside 'files' did not exist!", mDoBackupFile2.exists());
+ }
+
+ private void assertDollyFilesDontExist() {
+ assertFalse("File in 'files' did exist!", mDoBackupFile.exists());
+ assertFalse("File in folder inside 'files' did exist!", mDoBackupFile2.exists());
+ }
+}
diff --git a/hostsidetests/backup/RestoreAnyVersion/src/RestoreAnyVersionTest.java b/hostsidetests/backup/RestoreAnyVersion/src/RestoreAnyVersionTest.java
index a364b0e..1dbdb05 100644
--- a/hostsidetests/backup/RestoreAnyVersion/src/RestoreAnyVersionTest.java
+++ b/hostsidetests/backup/RestoreAnyVersion/src/RestoreAnyVersionTest.java
@@ -56,15 +56,6 @@
private static final int NEW_VERSION = 200;
private Context mContext;
- private CountDownLatch mLatch;
-
- private final BroadcastReceiver mSharedPrefencesReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.i(TAG, "received broadcast");
- mLatch.countDown();
- }
- };
@Before
public void setUp() {
diff --git a/hostsidetests/backup/src/android/cts/backup/FullBackupOnlyHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/FullBackupOnlyHostSideTest.java
new file mode 100644
index 0000000..7697dd2
--- /dev/null
+++ b/hostsidetests/backup/src/android/cts/backup/FullBackupOnlyHostSideTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.cts.backup;
+
+import static junit.framework.Assert.assertNull;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test checking that 'fullBackupOnly' manifest attribute is respected by backup manager.
+ *
+ * Uses 3 different versions of the same app that differ only by 'fullBackupOnly' value and the
+ * presence/absence of the backup agent.*
+ *
+ * Invokes device side tests provided by
+ * {@link android.cts.backup.fullbackupapp.FullBackupOnlyTest}.
+ *
+ * The flow of the tests is the following:
+ * 1. Install the app
+ * 2. Generate files in data folder of the app, including a file in no_backup folder. The file in
+ * no_backup folder is used for key/value backup by the backup agent of the app.
+ * 3. Run 'bmgr backupnow'. Depending on the manifest of the app we expect either Dolly or Key/value
+ * backup to be performed.
+ * 4. Uninstall and reinstall the app.
+ * 5. Check that the correct files were restored depending on the manifest:
+ * - Files in the app's data folder for Dolly backup
+ * - Only file in no_backup folder for key/value.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class FullBackupOnlyHostSideTest extends BaseBackupHostSideTest {
+
+ private static final String FULLBACKUPONLY_APP_PACKAGE = "android.cts.backup.fullbackuponlyapp";
+ private static final String FULLBACKUPONLY_DEVICE_TEST_CLASS_NAME =
+ FULLBACKUPONLY_APP_PACKAGE + ".FullBackupOnlyTest";
+
+ /**
+ * The name of the APK of the app that has a backup agent and fullBackupOnly=false in the
+ * manifest
+ */
+ private static final String FULLBACKUPONLY_FALSE_WITH_AGENT_APP_APK =
+ "FullBackupOnlyFalseWithAgentApp.apk";
+
+ /**
+ * The name of the APK of the app that has no backup agent and fullBackupOnly=false in the
+ * manifest
+ */
+ private static final String FULLBACKUPONLY_FALSE_NO_AGENT_APP_APK =
+ "FullBackupOnlyFalseNoAgentApp.apk";
+
+ /**
+ * The name of the APK of the app that has a backup agent and fullBackupOnly=true in the
+ * manifest
+ */
+ private static final String FULLBACKUPONLY_TRUE_WITH_AGENT_APP_APK =
+ "FullBackupOnlyTrueWithAgentApp.apk";
+
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+
+ // Clear backup data and uninstall the package (in that order!)
+ clearBackupDataInLocalTransport(FULLBACKUPONLY_APP_PACKAGE);
+ assertNull(uninstallPackage(FULLBACKUPONLY_APP_PACKAGE));
+ }
+
+ /**
+ * Tests that the app that doesn't have fullBackupOnly (same as fullBackupOnly=false by default)
+ * and has a backup agent will get key/value backup.
+ * We check that key/value data was restored after reinstall and dolly data was not.
+ */
+ @Test
+ public void testFullBackupOnlyFalse_WithAgent() throws Exception {
+ installPackage(FULLBACKUPONLY_FALSE_WITH_AGENT_APP_APK, "-d", "-r");
+
+ checkFullBackupOnlyDeviceTest("createFiles");
+
+ backupNowAndAssertSuccess(FULLBACKUPONLY_APP_PACKAGE);
+
+ assertNull(uninstallPackage(FULLBACKUPONLY_APP_PACKAGE));
+
+ installPackage(FULLBACKUPONLY_FALSE_WITH_AGENT_APP_APK, "-d", "-r");
+
+ checkFullBackupOnlyDeviceTest("checkKeyValueFileExists");
+ checkFullBackupOnlyDeviceTest("checkDollyFilesDontExist");
+ }
+
+ /**
+ * Tests that the app that doesn't have fullBackupOnly (same as fullBackupOnly=false by default)
+ * and has no backup agent will get Dolly backup.
+ * We check that key/value data was not restored after reinstall and dolly data was.
+ */
+ @Test
+ public void testFullBackupOnlyFalse_NoAgent() throws Exception {
+ installPackage(FULLBACKUPONLY_FALSE_NO_AGENT_APP_APK, "-d", "-r");
+
+ checkFullBackupOnlyDeviceTest("createFiles");
+
+ backupNowAndAssertSuccess(FULLBACKUPONLY_APP_PACKAGE);
+
+ assertNull(uninstallPackage(FULLBACKUPONLY_APP_PACKAGE));
+
+ installPackage(FULLBACKUPONLY_FALSE_NO_AGENT_APP_APK, "-d", "-r");
+
+ checkFullBackupOnlyDeviceTest("checkKeyValueFileDoesntExist");
+ checkFullBackupOnlyDeviceTest("checkDollyFilesExist");
+ }
+
+ /**
+ * Tests that the app that has fullBackupOnly=true and has a backup agent will only get
+ * Dolly backup.
+ * We check that key/value data was not restored after reinstall and dolly data was.
+ */
+ @Test
+ public void testFullBackupOnlyTrue_WithAgent() throws Exception {
+ installPackage(FULLBACKUPONLY_TRUE_WITH_AGENT_APP_APK, "-d", "-r");
+
+ checkFullBackupOnlyDeviceTest("createFiles");
+
+ backupNowAndAssertSuccess(FULLBACKUPONLY_APP_PACKAGE);
+
+ assertNull(uninstallPackage(FULLBACKUPONLY_APP_PACKAGE));
+
+ installPackage(FULLBACKUPONLY_TRUE_WITH_AGENT_APP_APK, "-d", "-r");
+
+ checkFullBackupOnlyDeviceTest("checkKeyValueFileDoesntExist");
+ checkFullBackupOnlyDeviceTest("checkDollyFilesExist");
+ }
+
+
+ private void checkFullBackupOnlyDeviceTest(String methodName)
+ throws DeviceNotAvailableException {
+ checkDeviceTest(FULLBACKUPONLY_APP_PACKAGE, FULLBACKUPONLY_DEVICE_TEST_CLASS_NAME,
+ methodName);
+ }
+}