Merge "Skip camera test on devices without a camera" into nougat-cts-dev
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 3c1a35f..2cfad0d 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -67,15 +67,11 @@
 
     <application android:label="@string/app_name"
             android:icon="@drawable/icon"
-            android:backupAgent="VerifierBackupAgent"
             android:debuggable="true"
             android:largeHeap="true">
 
         <meta-data android:name="SuiteName" android:value="CTS_VERIFIER" />
 
-        <meta-data android:name="com.google.android.backup.api_key"
-                android:value="AEdPqrEAAAAIbK6ldcOzoeRtQ1u1dFVJ1A7KetRhit-a1Xa82Q" />
-
         <uses-library android:name="android.test.runner"/>
 
         <activity android:name=".TestListActivity" android:label="@string/app_name" />
@@ -138,25 +134,6 @@
                     android:value="android.software.device_admin" />
         </activity>
 
-        <activity android:name=".backup.BackupTestActivity" android:label="@string/backup_test">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.cts.intent.category.MANUAL_TEST" />
-            </intent-filter>
-            <meta-data android:name="test_required_features"
-                    android:value="android.software.backup" />
-        </activity>
-
-	<!-- Further work is required for this test, b/32798562  -->
-        <!-- activity android:name=".backup.BackupAccessibilityTestActivity" android:label="@string/backup_accessibility_test">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.cts.intent.category.MANUAL_TEST" />
-            </intent-filter>
-            <meta-data android:name="test_required_features"
-                    android:value="android.software.backup" />
-        </activity -->
-
         <activity android:name=".bluetooth.BluetoothTestActivity"
                 android:label="@string/bluetooth_test"
                 android:configChanges="keyboardHidden|orientation|screenSize">
diff --git a/apps/CtsVerifier/res/layout/bu_main.xml b/apps/CtsVerifier/res/layout/bu_main.xml
deleted file mode 100644
index 2289fee..0000000
--- a/apps/CtsVerifier/res/layout/bu_main.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-         android:orientation="vertical"
-         android:layout_width="match_parent"
-         android:layout_height="match_parent"
-         >
-         
-    <ListView android:id="@+id/android:list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            />
-            
-    <TextView android:id="@id/android:empty"
-           android:gravity="center"
-           android:layout_width="match_parent"
-           android:layout_height="wrap_content"
-           android:layout_weight="1"
-           android:text="@string/bu_loading"
-           />
-
-    <Button android:id="@+id/generate_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bu_generate"
-            />
-
-    <include layout="@layout/pass_fail_buttons" />
-
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/bu_preference_row.xml b/apps/CtsVerifier/res/layout/bu_preference_row.xml
deleted file mode 100644
index c37eece..0000000
--- a/apps/CtsVerifier/res/layout/bu_preference_row.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textSize="18sp"
-        android:padding="5dp"
-        />
diff --git a/apps/CtsVerifier/res/layout/bua_main.xml b/apps/CtsVerifier/res/layout/bua_main.xml
deleted file mode 100644
index e2d5ef1..0000000
--- a/apps/CtsVerifier/res/layout/bua_main.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-         android:orientation="vertical"
-         android:layout_width="match_parent"
-         android:layout_height="match_parent"
-         >
-
-    <ListView android:id="@+id/android:list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            />
-
-    <TextView android:id="@id/android:empty"
-           android:gravity="center"
-           android:layout_width="match_parent"
-           android:layout_height="wrap_content"
-           android:layout_weight="1"
-           android:text="@string/bu_loading"
-           />
-
-    <Button android:id="@+id/generate_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bua_read_settings"
-            />
-
-    <Button android:id="@+id/show_instructions_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bua_show_instructions"
-            />
-
-    <include layout="@layout/pass_fail_buttons" />
-
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 49d249d..91ca7c7 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -60,71 +60,6 @@
     <string name="bu_generate_error">Error occurred while generating test data...</string>
     <string name="bu_settings">Settings</string>
 
-    <!-- Strings for BackupTestActivity -->
-    <string name="backup_test">Data Backup Test</string>
-    <string name="backup_info">This test checks that data backup and automatic restore works
-        properly. The test activity lists some preferences and files that are backed up and
-        restored by the CTS Verifier. If backup and restore is working properly, these values
-        should be restored after running the backup manager, uninstalling the app, and reinstalling
-        the CTS Verifier.
-        \n\nPress the \"Generate Test Data\" to populate these values
-        and then follow the on screen instructions to finish the test.
-    </string>
-    <string name="bu_generate">Generate Test Data</string>
-    <string name="bu_preferences">Preferences</string>
-    <string name="bu_files">Files</string>
-    <string name="bu_instructions">Random values for the preferences and files have been saved.
-        \n\nFollow the instructions below to check that the data backup and restore works:
-        \n\n1. Make sure backup and automatic restore are enabled in settings. Depending on the
-        backup transport supported by the device you may need to do additional steps. For instance
-        you may need to set a Google account as the backup account for the device. If you cannot
-        find the corresponding setting options on your device, run \"adb shell bmgr enable true\"
-        to enable the backup manager. You can check its status by executing \"adb shell bmgr
-        enabled\".
-        \n\n2. Run the backup manager: adb shell bmgr run
-        \n\n3. Uninstall the program: adb uninstall com.android.cts.verifier
-        \n\n4. Reinstall the CTS Verifier and verify that the values are still the same.
-    </string>
-
-    <!-- Strings for BackupAccessibilityTestActivity -->
-    <string name="backup_accessibility_test">Backup Accessibility Settings Test</string>
-    <string name="backup_accessibility_info">This test checks that data backup and automatic restore
-        of Accessibility-related settings works properly. If backup and restore is working properly,
-        these values should be restored after running the backup manager, removing your Google
-        account, changing the accessibility settings values, and re-adding your Google account.
-        \n\nPress \"Generate Test Data\" to generate test values for accessibility settings and then
-        follow the on screen instructions to finish the test.
-    </string>
-    <string name="bua_settings">General Accessibility Settings</string>
-    <string name="bua_settings_color_correction">Color Correction Settings</string>
-    <string name="bua_settings_accessibility_services">Accessibility Service Settings</string>
-    <string name="bua_settings_captions">Captions Settings</string>
-    <string name="bua_settings_tts">TTS Settings</string>
-    <string name="bua_settings_system">Other System Settings</string>
-    <string name="bua_instructions">You will need two devices for this test.
-        \n\nFollow the instructions below to check that the data backup and restore of
-        accessibility-related settings works properly:
-        \n\n1. Make sure backup and automatic restore are enabled in settings. If you cannot find
-        the corresponding setting options on your device, run \"adb shell bmgr enable true\" to
-        enable the backup manager. You can check its status by executing \"adb shell bmgr enabled\".
-        You will also need to set a Google account as the backup account for the device.
-        \n\n2. Press \"Read Current Values\" and note the default values for the listed settings.
-        Values that are either \"0\" or \"null\" will appear in green. Note: Some default values are
-        neither \"0\", nor \"null\", so you still need to pay attention to the default setting
-        values that are not highlighted.
-        \n\n3. Change the values of the listed settings to something other than their default value.
-        \n\n4. Return to the CtsVerifier and press \"Read Current Values\". Make sure that you have
-        changed all of the settings.
-        \n\n5. Run the backup manager: adb shell bmgr run
-        \n\n6. Factory reset data on the second device. While going through the Setup Wizard,
-        restore all data from the account on your first device. When prompted, choose to restore all
-        settings from your first device.
-        \n\n7. Install CtsVerifier on your new device and make sure that the values read on the
-        second device match the values on your first device.
-    </string>
-    <string name="bua_show_instructions">Show Instructions</string>
-    <string name="bua_read_settings">Read Current Values</string>
-
     <!-- Strings for Device Administration tests -->
     <string name="da_policy_serialization_test">Policy Serialization Test</string>
     <string name="da_policy_serialization_info">This test checks that a device policy is properly
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java
deleted file mode 100644
index 2527d57..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.cts.verifier;
-
-import com.android.cts.verifier.backup.BackupTestActivity;
-
-import android.app.backup.BackupDataInputStream;
-import android.app.backup.BackupDataOutput;
-import android.app.backup.BackupHelper;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-/** {@link BackupHelper} for the test results database. */
-class TestResultsBackupHelper implements BackupHelper {
-
-    private static final String TAG = TestResultsBackupHelper.class.getSimpleName();
-
-    private static final String DB_BACKUP_KEY = "db";
-
-    private final Context mContext;
-
-    TestResultsBackupHelper(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
-            ParcelFileDescriptor newState) {
-        ContentResolver resolver = mContext.getContentResolver();
-        Cursor cursor = null;
-        try {
-            cursor = resolver.query(TestResultsProvider.getResultContentUri(mContext),
-                    null, null, null, null);
-            int nameIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_NAME);
-            int resultIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_RESULT);
-            int infoSeenIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_INFO_SEEN);
-            int detailsIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_DETAILS);
-            int metricsIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_METRICS);
-
-            ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
-            DataOutputStream dataOutput = new DataOutputStream(byteOutput);
-
-            dataOutput.writeInt(cursor.getCount());
-            while (cursor.moveToNext()) {
-                String name = cursor.getString(nameIndex);
-                int result = cursor.getInt(resultIndex);
-                int infoSeen = cursor.getInt(infoSeenIndex);
-                String details = cursor.getString(detailsIndex);
-                byte[] metricsData = cursor.getBlob(metricsIndex);
-
-                dataOutput.writeUTF(name);
-                dataOutput.writeInt(result);
-                dataOutput.writeInt(infoSeen);
-                dataOutput.writeUTF(details != null ? details : "");
-                dataOutput.writeInt(metricsData.length);
-                if (metricsData.length > 0) {
-                    dataOutput.write(metricsData);
-                }
-            }
-
-            byte[] rawBytes = byteOutput.toByteArray();
-            data.writeEntityHeader(DB_BACKUP_KEY, rawBytes.length);
-            data.writeEntityData(rawBytes, rawBytes.length);
-        } catch (IOException e) {
-            Log.e(TAG, "Couldn't backup test results...", e);
-            failBackupTest();
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-    }
-
-    @Override
-    public void restoreEntity(BackupDataInputStream data) {
-        try {
-            if (DB_BACKUP_KEY.equals(data.getKey())) {
-                byte[] rawBytes = new byte[data.size()];
-                data.read(rawBytes, 0, data.size());
-
-                ByteArrayInputStream byteInput = new ByteArrayInputStream(rawBytes);
-                DataInputStream dataInput = new DataInputStream(byteInput);
-
-                int numRows = dataInput.readInt();
-                ContentValues[] values = new ContentValues[numRows];
-                for (int i = 0; i < numRows; i++) {
-                    String name = dataInput.readUTF();
-                    int result = dataInput.readInt();
-                    int infoSeen = dataInput.readInt();
-                    String details = dataInput.readUTF();
-                    int metricsDataSize = dataInput.readInt();
-
-                    values[i] = new ContentValues();
-                    values[i].put(TestResultsProvider.COLUMN_TEST_NAME, name);
-                    values[i].put(TestResultsProvider.COLUMN_TEST_RESULT, result);
-                    values[i].put(TestResultsProvider.COLUMN_TEST_INFO_SEEN, infoSeen);
-                    values[i].put(TestResultsProvider.COLUMN_TEST_DETAILS, details);
-
-                    if (metricsDataSize > 0) {
-                        byte[] metrics = new byte[metricsDataSize];
-                        dataInput.readFully(metrics);
-                        values[i].put(TestResultsProvider.COLUMN_TEST_METRICS, metrics);
-                    }
-                }
-
-                ContentResolver resolver = mContext.getContentResolver();
-                resolver.bulkInsert(TestResultsProvider.getResultContentUri(mContext), values);
-            } else {
-                Log.e(TAG, "Skipping key: " + data.getKey());
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "Couldn't restore test results...", e);
-            failBackupTest();
-        }
-    }
-
-    private void failBackupTest() {
-        TestResultsProvider.setTestResult(mContext, BackupTestActivity.class.getName(),
-                TestResult.TEST_RESULT_FAILED, null /*testDetails*/, null /*testMetrics*/);
-    }
-
-    @Override
-    public void writeNewStateDescription(ParcelFileDescriptor newState) {
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/VerifierBackupAgent.java b/apps/CtsVerifier/src/com/android/cts/verifier/VerifierBackupAgent.java
deleted file mode 100644
index 3c980b9..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/VerifierBackupAgent.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.cts.verifier;
-
-import com.android.cts.verifier.backup.BackupTestActivity;
-
-import android.app.backup.BackupAgentHelper;
-
-public class VerifierBackupAgent extends BackupAgentHelper {
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        addHelper("test-results", new TestResultsBackupHelper(this));
-        addHelper("backup-test-prefs", BackupTestActivity.getSharedPreferencesBackupHelper(this));
-        addHelper("backup-test-files", BackupTestActivity.getFileBackupHelper(this));
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupAccessibilityTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupAccessibilityTestActivity.java
deleted file mode 100644
index 157a71c..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupAccessibilityTestActivity.java
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.cts.verifier.backup;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.backup.BackupManager;
-import android.app.backup.FileBackupHelper;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.graphics.Color;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.Scanner;
-
-/**
- * Test for checking whether Accessibility Settings are being backed up properly. It lists the
- * values of the accessibility preferences that should get backed up and restored after running the
- * backup manager and reinstalling the CTS verifier.
- */
-public class BackupAccessibilityTestActivity extends PassFailButtons.ListActivity {
-
-    private static final String TAG = BackupAccessibilityTestActivity.class.getSimpleName();
-
-    private static final int INSTRUCTIONS_DIALOG_ID = 1;
-
-    private static final List<String> ACCESSIBILITY_SETTINGS = new ArrayList();
-    private static final List<String> COLOR_CORRECTION_SETTINGS = new ArrayList();
-    private static final List<String> ACCESSIBILITY_SERVICE_SETTINGS = new ArrayList();
-    private static final List<String> CAPTIONS_SETTINGS = new ArrayList();
-    private static final List<String> TTS_SETTINGS = new ArrayList();
-    private static final List<String> SYSTEM_SETTINGS = new ArrayList();
-
-    static {
-        ACCESSIBILITY_SETTINGS.add("accessibility_display_magnification_enabled");
-        ACCESSIBILITY_SETTINGS.add("accessibility_autoclick_enabled");
-        ACCESSIBILITY_SETTINGS.add("accessibility_autoclick_delay");
-        ACCESSIBILITY_SETTINGS.add("high_text_contrast_enabled");
-        ACCESSIBILITY_SETTINGS.add("incall_power_button_behavior");
-        ACCESSIBILITY_SETTINGS.add(Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD);
-        ACCESSIBILITY_SETTINGS.add("accessibility_large_pointer_icon");
-        ACCESSIBILITY_SETTINGS.add("long_press_timeout");
-        ACCESSIBILITY_SETTINGS.add(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
-
-        COLOR_CORRECTION_SETTINGS.add("accessibility_display_daltonizer");
-        COLOR_CORRECTION_SETTINGS.add("accessibility_display_daltonizer_enabled");
-
-        CAPTIONS_SETTINGS.add("accessibility_captioning_preset");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_enabled");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_locale");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_background_color");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_foreground_color");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_edge_type");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_edge_color");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_typeface");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_font_scale");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_window_color");
-
-        TTS_SETTINGS.add(Settings.Secure.TTS_DEFAULT_RATE);
-        TTS_SETTINGS.add("tts_default_locale");
-
-        ACCESSIBILITY_SERVICE_SETTINGS.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
-        ACCESSIBILITY_SERVICE_SETTINGS.add("touch_exploration_granted_accessibility_services");
-        ACCESSIBILITY_SERVICE_SETTINGS.add(Settings.Secure.TOUCH_EXPLORATION_ENABLED);
-
-        SYSTEM_SETTINGS.add(Settings.System.FONT_SCALE);
-        SYSTEM_SETTINGS.add(Settings.System.STAY_ON_WHILE_PLUGGED_IN);
-        SYSTEM_SETTINGS.add(Settings.System.SCREEN_OFF_TIMEOUT);
-        SYSTEM_SETTINGS.add(Settings.System.SCREEN_BRIGHTNESS);
-        SYSTEM_SETTINGS.add(Settings.System.SCREEN_BRIGHTNESS_MODE);
-        SYSTEM_SETTINGS.add(Settings.System.TEXT_SHOW_PASSWORD);
-        SYSTEM_SETTINGS.add(Settings.System.HAPTIC_FEEDBACK_ENABLED);
-        SYSTEM_SETTINGS.add("power_sounds_enabled");
-        SYSTEM_SETTINGS.add("lockscreen_sounds_enabled");
-        SYSTEM_SETTINGS.add("pointer_speed");
-        SYSTEM_SETTINGS.add(Settings.System.VIBRATE_WHEN_RINGING);
-        SYSTEM_SETTINGS.add(Settings.System.ACCELEROMETER_ROTATION);
-    }
-
-    private BackupAdapter mAdapter;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-        setContentView(R.layout.bua_main);
-        setPassFailButtonClickListeners();
-        setInfoResources(R.string.backup_accessibility_test, R.string.backup_accessibility_info, 0);
-
-        mAdapter = new BackupAdapter(this);
-        setListAdapter(mAdapter);
-
-        new ReadCurrentSettingsValuesTask().execute();
-
-        findViewById(R.id.generate_button).setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                new ReadCurrentSettingsValuesTask().execute();
-            }
-        });
-
-        findViewById(R.id.show_instructions_button).setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                showDialog(INSTRUCTIONS_DIALOG_ID);
-            }
-        });
-    }
-
-    class ReadCurrentSettingsValuesTask extends AsyncTask<Void, Void, List<BackupItem>> {
-
-        @Override
-        protected void onPreExecute() {
-            super.onPreExecute();
-            setProgressBarIndeterminateVisibility(true);
-        }
-
-        @Override
-        protected List<BackupItem> doInBackground(Void... params) {
-            List<BackupItem> items = new ArrayList<BackupItem>();
-
-            items.add(new CategoryBackupItem(R.string.bua_settings));
-            addSecureSettings(items, ACCESSIBILITY_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_color_correction));
-            addSecureSettings(items, COLOR_CORRECTION_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_captions));
-            addSecureSettings(items, CAPTIONS_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_tts));
-            addSecureSettings(items, TTS_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_accessibility_services));
-            addSecureSettings(items, ACCESSIBILITY_SERVICE_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_system));
-            addSystemSettings(items, SYSTEM_SETTINGS);
-
-            return items;
-        }
-
-        private void addSecureSettings(List<BackupItem> items, List<String> settings) {
-            for (String setting : settings) {
-                String value = Settings.Secure.getString(getContentResolver(), setting);
-                items.add(new PreferenceBackupItem(setting, value));
-            }
-        }
-
-        private void addSystemSettings(List<BackupItem> items, List<String> settings) {
-            for (String setting : settings) {
-                String value = Settings.System.getString(getContentResolver(), setting);
-                items.add(new PreferenceBackupItem(setting, value));
-            }
-        }
-
-        @Override
-        protected void onPostExecute(List<BackupItem> result) {
-            super.onPostExecute(result);
-            setProgressBarIndeterminateVisibility(false);
-            mAdapter.clear();
-            mAdapter.addAll(result);
-        }
-    }
-
-    @Override
-    public Dialog onCreateDialog(int id, Bundle args) {
-        switch (id) {
-            case INSTRUCTIONS_DIALOG_ID:
-                return new AlertDialog.Builder(this)
-                    .setIcon(android.R.drawable.ic_dialog_info)
-                    .setTitle(R.string.backup_accessibility_test)
-                    .setMessage(R.string.bua_instructions)
-                    .setPositiveButton(android.R.string.ok, null)
-                    .setNeutralButton(R.string.bu_settings, new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            startActivity(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
-                        }
-                    }).create();
-
-            default:
-                return super.onCreateDialog(id, args);
-        }
-    }
-
-    interface BackupItem {
-        int getViewType();
-        View getView(LayoutInflater inflater, int position, View convertView, ViewGroup parent);
-    }
-
-    static class CategoryBackupItem implements BackupItem {
-
-        private final int mTitleResId;
-
-        CategoryBackupItem(int titleResId) {
-            mTitleResId = titleResId;
-        }
-
-        @Override
-        public int getViewType() {
-            return 0;
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.test_category_row, parent, false);
-            }
-            view.setText(mTitleResId);
-            view.setAllCaps(true);
-            view.setTextAppearance(1);  // Bold
-            return view;
-        }
-    }
-
-    static class PreferenceBackupItem implements BackupItem {
-
-        private final String mName;
-        private final String mValue;
-
-        PreferenceBackupItem(String name, String value) {
-            mName = name;
-            mValue = value;
-        }
-
-        @Override
-        public int getViewType() {
-            if (mValue == null || mValue.equals("0")) {
-                return 1;
-            } else {
-                return 2;
-            }
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.bu_preference_row, parent, false);
-            }
-            view.setText(mName + " : " + mValue);
-            if (mValue == null || mValue.equals("0")) {
-                view.setTextColor(Color.GREEN);
-            }
-            return view;
-        }
-    }
-
-    class BackupAdapter extends BaseAdapter {
-
-        private final LayoutInflater mLayoutInflater;
-
-        private final List<BackupItem> mItems = new ArrayList<BackupItem>();
-
-        public BackupAdapter(Context context) {
-            mLayoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
-        }
-
-        public void clear() {
-            mItems.clear();
-        }
-
-        public void addAll(List<BackupItem> items) {
-            mItems.addAll(items);
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public int getCount() {
-            return mItems.size();
-        }
-
-        @Override
-        public BackupItem getItem(int position) {
-            return mItems.get(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public boolean isEnabled(int position) {
-            return false;
-        }
-
-        @Override
-        public int getViewTypeCount() {
-            return 3;
-        }
-
-        @Override
-        public int getItemViewType(int position) {
-            return getItem(position).getViewType();
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            return getItem(position).getView(mLayoutInflater, position, convertView, parent);
-        }
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupTestActivity.java
deleted file mode 100644
index cccc1c2..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupTestActivity.java
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.cts.verifier.backup;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.backup.BackupManager;
-import android.app.backup.FileBackupHelper;
-import android.app.backup.SharedPreferencesBackupHelper;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.Scanner;
-
-/**
- * Test for checking whether the BackupManager is working properly. It lists the values of
- * several preferences and contents of files that should get backed up and restored after
- * running the backup manager and reinstalling the CTS verifier.
- */
-public class BackupTestActivity extends PassFailButtons.ListActivity {
-
-    private static final String TAG = BackupTestActivity.class.getSimpleName();
-
-    private static final int INSTRUCTIONS_DIALOG_ID = 1;
-
-    private static final String TEST_PREFS_1 = "test-prefs-1";
-    private static final String INT_PREF = "int-pref";
-    private static final String BOOL_PREF = "bool-pref";
-
-    private static final String TEST_PREFS_2 = "test-prefs-2";
-    private static final String FLOAT_PREF = "float-pref";
-    private static final String LONG_PREF = "long-pref";
-    private static final String STRING_PREF = "string-pref";
-
-    private static final String TEST_FILE_1 = "test-file-1";
-    private static final String TEST_FILE_2 = "test-file-2";
-
-    private BackupAdapter mAdapter;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-        setContentView(R.layout.bu_main);
-        setPassFailButtonClickListeners();
-        setInfoResources(R.string.backup_test, R.string.backup_info, 0);
-
-        mAdapter = new BackupAdapter(this);
-        setListAdapter(mAdapter);
-
-        new LoadBackupItemsTask().execute();
-
-        findViewById(R.id.generate_button).setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                new GenerateValuesTask().execute();
-            }
-        });
-    }
-
-    public static SharedPreferencesBackupHelper getSharedPreferencesBackupHelper(Context context) {
-        return new SharedPreferencesBackupHelper(context, TEST_PREFS_1, TEST_PREFS_2);
-    }
-
-    public static FileBackupHelper getFileBackupHelper(Context context) {
-        return new FileBackupHelper(context, TEST_FILE_1, TEST_FILE_2);
-    }
-
-    class LoadBackupItemsTask extends AsyncTask<Void, Void, List<BackupItem>> {
-
-        @Override
-        protected void onPreExecute() {
-            super.onPreExecute();
-            setProgressBarIndeterminateVisibility(true);
-        }
-
-        @Override
-        protected List<BackupItem> doInBackground(Void... params) {
-            List<BackupItem> items = new ArrayList<BackupItem>();
-
-            items.add(new CategoryBackupItem(R.string.bu_preferences));
-            loadPreferenceGroup1(items);
-            loadPreferenceGroup2(items);
-
-            items.add(new CategoryBackupItem(R.string.bu_files));
-            loadFile(TEST_FILE_1, items);
-            loadFile(TEST_FILE_2, items);
-
-            return items;
-        }
-
-        private void loadPreferenceGroup1(List<BackupItem> items) {
-            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
-
-            int intValue = prefs.getInt(INT_PREF, 0);
-            items.add(new PreferenceBackupItem(TEST_PREFS_1, INT_PREF, "" + intValue));
-
-            boolean boolValue = prefs.getBoolean(BOOL_PREF, false);
-            items.add(new PreferenceBackupItem(TEST_PREFS_1, BOOL_PREF, "" + boolValue));
-        }
-
-        private void loadPreferenceGroup2(List<BackupItem> items) {
-            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
-
-            float floatValue = prefs.getFloat(FLOAT_PREF, 0.0f);
-            items.add(new PreferenceBackupItem(TEST_PREFS_2, FLOAT_PREF, "" + floatValue));
-
-            long longValue = prefs.getLong(LONG_PREF, 0L);
-            items.add(new PreferenceBackupItem(TEST_PREFS_2, LONG_PREF, "" + longValue));
-
-            String stringValue = prefs.getString(STRING_PREF, null);
-            items.add(new PreferenceBackupItem(TEST_PREFS_2, STRING_PREF, stringValue));
-        }
-
-        private void loadFile(String fileName, List<BackupItem> items) {
-            StringBuilder contents = new StringBuilder();
-            Scanner scanner = null;
-            try {
-                scanner = new Scanner(new File(getFilesDir(), fileName));
-                while (scanner.hasNext()) {
-                    contents.append(scanner.nextLine());
-                }
-                scanner.close();
-            } catch (FileNotFoundException e) {
-                Log.e(TAG, "Couldn't find test file but this may be fine...", e);
-            } finally {
-                if (scanner != null) {
-                    scanner.close();
-                }
-            }
-            items.add(new FileBackupItem(fileName, contents.toString()));
-        }
-
-        @Override
-        protected void onPostExecute(List<BackupItem> result) {
-            super.onPostExecute(result);
-            setProgressBarIndeterminateVisibility(false);
-            mAdapter.clear();
-            mAdapter.addAll(result);
-        }
-    }
-
-    class GenerateValuesTask extends AsyncTask<Void, Void, Exception> {
-
-        @Override
-        protected Exception doInBackground(Void... params) {
-            Random random = new Random();
-            generatePreferenceGroup1(random);
-            generatePreferenceGroup2(random);
-            try {
-                generateTestFile(TEST_FILE_1, random);
-                generateTestFile(TEST_FILE_2, random);
-            } catch (FileNotFoundException e) {
-                return e;
-            }
-            return null;
-        }
-
-        private void generatePreferenceGroup1(Random random) {
-            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
-            SharedPreferences.Editor editor = prefs.edit();
-            editor.putInt(INT_PREF, (random.nextInt(100) + 1));
-            editor.putBoolean(BOOL_PREF, random.nextBoolean());
-            editor.commit();
-        }
-
-        private void generatePreferenceGroup2(Random random) {
-            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
-            SharedPreferences.Editor editor = prefs.edit();
-            editor.putFloat(FLOAT_PREF, random.nextFloat());
-            editor.putLong(LONG_PREF, random.nextLong());
-            editor.putString(STRING_PREF, "Random number: " + (random.nextInt(100) + 1));
-            editor.commit();
-        }
-
-        private void generateTestFile(String fileName, Random random)
-                throws FileNotFoundException {
-            File file = new File(getFilesDir(), fileName);
-            PrintWriter writer = new PrintWriter(file);
-            writer.write("Random number: " + (random.nextInt(100) + 1));
-            writer.close();
-        }
-
-        @Override
-        protected void onPostExecute(Exception exception) {
-            super.onPostExecute(exception);
-            if (exception != null) {
-                Log.e(TAG, "Couldn't generate test data...", exception);
-                Toast.makeText(BackupTestActivity.this, R.string.bu_generate_error,
-                        Toast.LENGTH_LONG).show();
-            } else {
-                showDialog(INSTRUCTIONS_DIALOG_ID);
-
-                BackupManager backupManager = new BackupManager(BackupTestActivity.this);
-                backupManager.dataChanged();
-
-                new LoadBackupItemsTask().execute();
-            }
-        }
-    }
-
-    @Override
-    public Dialog onCreateDialog(int id, Bundle args) {
-        switch (id) {
-            case INSTRUCTIONS_DIALOG_ID:
-                return new AlertDialog.Builder(this)
-                    .setIcon(android.R.drawable.ic_dialog_info)
-                    .setTitle(R.string.backup_test)
-                    .setMessage(R.string.bu_instructions)
-                    .setPositiveButton(android.R.string.ok, null)
-                    .setNeutralButton(R.string.bu_settings, new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            startActivity(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
-                        }
-                    })
-                    .create();
-
-            default:
-                return super.onCreateDialog(id, args);
-        }
-    }
-
-    interface BackupItem {
-        int getViewType();
-        View getView(LayoutInflater inflater, int position, View convertView, ViewGroup parent);
-    }
-
-    static class CategoryBackupItem implements BackupItem {
-
-        private final int mTitleResId;
-
-        CategoryBackupItem(int titleResId) {
-            mTitleResId = titleResId;
-        }
-
-        @Override
-        public int getViewType() {
-            return 0;
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.test_category_row, parent, false);
-            }
-            view.setText(mTitleResId);
-            return view;
-        }
-    }
-
-    static class PreferenceBackupItem implements BackupItem {
-
-        private final String mGroup;
-
-        private final String mName;
-
-        private final String mValue;
-
-        PreferenceBackupItem(String group, String name, String value) {
-            mGroup = group;
-            mName = name;
-            mValue = value;
-        }
-
-        @Override
-        public int getViewType() {
-            return 1;
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.bu_preference_row, parent, false);
-            }
-            view.setText(mGroup + "/" + mName + " : " + mValue);
-            return view;
-        }
-    }
-
-    static class FileBackupItem implements BackupItem {
-
-        private final String mName;
-
-        private final String mContents;
-
-        FileBackupItem(String name, String contents) {
-            mName = name;
-            mContents = contents;
-        }
-
-        @Override
-        public int getViewType() {
-            return 2;
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.bu_preference_row, parent, false);
-            }
-            view.setText(mName + " : " + mContents);
-            return view;
-        }
-    }
-
-    class BackupAdapter extends BaseAdapter {
-
-        private final LayoutInflater mLayoutInflater;
-
-        private final List<BackupItem> mItems = new ArrayList<BackupItem>();
-
-        public BackupAdapter(Context context) {
-            mLayoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
-        }
-
-        public void clear() {
-            mItems.clear();
-        }
-
-        public void addAll(List<BackupItem> items) {
-            mItems.addAll(items);
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public int getCount() {
-            return mItems.size();
-        }
-
-        @Override
-        public BackupItem getItem(int position) {
-            return mItems.get(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public boolean isEnabled(int position) {
-            return false;
-        }
-
-        @Override
-        public int getViewTypeCount() {
-            return 3;
-        }
-
-        @Override
-        public int getItemViewType(int position) {
-            return getItem(position).getViewType();
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            return getItem(position).getView(mLayoutInflater, position, convertView, parent);
-        }
-    }
-}
diff --git a/hostsidetests/backup/Android.mk b/hostsidetests/backup/Android.mk
new file mode 100644
index 0000000..194341b
--- /dev/null
+++ b/hostsidetests/backup/Android.mk
@@ -0,0 +1,36 @@
+# 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)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_RESOURCE_DIRS := assets/
+
+LOCAL_MODULE_TAGS := tests
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_MODULE := CtsBackupHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt compatibility-host-util
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/backup/AndroidTest.xml b/hostsidetests/backup/AndroidTest.xml
new file mode 100644
index 0000000..2ea4663
--- /dev/null
+++ b/hostsidetests/backup/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Backup host test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsBackupRestoreDeviceApp.apk" />
+        <option name="test-file-name" value="CtsFullbackupApp.apk" />
+    </target_preparer>
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsBackupHostTestCases.jar" />
+    </test>
+</configuration>
diff --git a/hostsidetests/backup/app/Android.mk b/hostsidetests/backup/app/Android.mk
new file mode 100644
index 0000000..248207c
--- /dev/null
+++ b/hostsidetests/backup/app/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 := CtsBackupRestoreDeviceApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/backup/app/AndroidManifest.xml b/hostsidetests/backup/app/AndroidManifest.xml
new file mode 100644
index 0000000..0d3aee8
--- /dev/null
+++ b/hostsidetests/backup/app/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?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.backup.cts.backuprestoreapp">
+
+    <application
+        android:backupAgent="CtsBackupRestoreBackupAgent">
+        <uses-library android:name="android.test.runner" />
+
+        <activity
+            android:name=".KeyValueBackupRandomDataActivity"
+            android:launchMode="singleInstance">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.backup.cts.backuprestoreapp" />
+
+</manifest>
diff --git a/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/CtsBackupRestoreBackupAgent.java b/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/CtsBackupRestoreBackupAgent.java
new file mode 100644
index 0000000..e692fdd
--- /dev/null
+++ b/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/CtsBackupRestoreBackupAgent.java
@@ -0,0 +1,33 @@
+/*
+ * 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.backup.cts.backuprestoreapp;
+
+import android.app.backup.BackupAgentHelper;
+
+public class CtsBackupRestoreBackupAgent extends BackupAgentHelper {
+    private static final String KEY_BACKUP_TEST_PREFS_PREFIX = "backup-test-prefs";
+    private static final String KEY_BACKUP_TEST_FILES_PREFIX = "backup-test-files";
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        addHelper(KEY_BACKUP_TEST_PREFS_PREFIX,
+                KeyValueBackupRandomDataActivity.getSharedPreferencesBackupHelper(this));
+        addHelper(KEY_BACKUP_TEST_FILES_PREFIX,
+                KeyValueBackupRandomDataActivity.getFileBackupHelper(this));
+    }
+}
diff --git a/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/KeyValueBackupRandomDataActivity.java b/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/KeyValueBackupRandomDataActivity.java
new file mode 100644
index 0000000..92db3f3
--- /dev/null
+++ b/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/KeyValueBackupRandomDataActivity.java
@@ -0,0 +1,228 @@
+/*
+ * 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.backup.cts.backuprestoreapp;
+
+import android.app.Activity;
+import android.app.backup.BackupManager;
+import android.app.backup.FileBackupHelper;
+import android.app.backup.SharedPreferencesBackupHelper;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.Random;
+import java.util.Scanner;
+
+/**
+ * Test activity that reads/writes to shared preferences and files.
+ *
+ * It uses logcat messages to send the data to the host side of the test.
+ * The format of logcat messages: "DATA_PREF: VALUE".
+ * VALUES_LOADED_MESSAGE is logged after all the values.
+ *
+ * Workflow onCreate:
+ * - Read shared preferences and files
+ * - If the values are default ones:
+ *      - Randomly generate new values
+ *      - Save new values to shared preferences and files
+ *      - Load the new values.
+ *
+ * Migrated from BackupTestActivity in former BackupTest CTS Verfifier test.
+ */
+public class KeyValueBackupRandomDataActivity extends Activity {
+    private static final String TAG = KeyValueBackupRandomDataActivity.class.getSimpleName();
+
+    private static final String TEST_PREFS_1 = "test-prefs-1";
+    private static final String INT_PREF = "int-pref";
+    private static final String BOOL_PREF = "bool-pref";
+
+    private static final String TEST_PREFS_2 = "test-prefs-2";
+    private static final String FLOAT_PREF = "float-pref";
+    private static final String LONG_PREF = "long-pref";
+    private static final String STRING_PREF = "string-pref";
+
+    private static final String TEST_FILE_1 = "test-file-1";
+    private static final String TEST_FILE_2 = "test-file-2";
+
+    private static final int DEFAULT_INT_VALUE = 0;
+    private static final boolean DEFAULT_BOOL_VALUE = false;
+    private static final float DEFAULT_FLOAT_VALUE = 0.0f;
+    private static final long DEFAULT_LONG_VALUE = 0L;
+    private static final String DEFAULT_STRING_VALUE = null;
+
+    private static final String VALUES_LOADED_MESSAGE = "ValuesLoaded";
+    private static final String EMPTY_STRING_LOG = "empty";
+
+    private boolean mDefaultValues = true;
+    private boolean mValuesWereGenerated;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        new LoadBackupItemsTask().execute();
+    }
+
+    public static SharedPreferencesBackupHelper getSharedPreferencesBackupHelper(Context context) {
+        return new SharedPreferencesBackupHelper(context, TEST_PREFS_1, TEST_PREFS_2);
+    }
+
+    public static FileBackupHelper getFileBackupHelper(Context context) {
+        return new FileBackupHelper(context, TEST_FILE_1, TEST_FILE_2);
+    }
+
+    class LoadBackupItemsTask extends AsyncTask<Void, Void, Void> {
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            loadPreferenceGroup1();
+            loadPreferenceGroup2();
+            loadFile(TEST_FILE_1);
+            loadFile(TEST_FILE_2);
+            return null;
+        }
+
+        private void loadPreferenceGroup1() {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
+
+            int intValue = prefs.getInt(INT_PREF, DEFAULT_INT_VALUE);
+            Log.i(TAG, INT_PREF + ":" + intValue);
+
+            boolean boolValue = prefs.getBoolean(BOOL_PREF, DEFAULT_BOOL_VALUE);
+            Log.i(TAG, BOOL_PREF + ":" + boolValue);
+
+            mDefaultValues = mDefaultValues
+                    && intValue == DEFAULT_INT_VALUE
+                    && boolValue == DEFAULT_BOOL_VALUE;
+        }
+
+        private void loadPreferenceGroup2() {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
+
+            float floatValue = prefs.getFloat(FLOAT_PREF, DEFAULT_FLOAT_VALUE);
+            Log.i(TAG, FLOAT_PREF + ":" + floatValue);
+
+            long longValue = prefs.getLong(LONG_PREF, DEFAULT_LONG_VALUE);
+            Log.i(TAG, LONG_PREF + ":" + longValue);
+
+            String stringValue = prefs.getString(STRING_PREF, DEFAULT_STRING_VALUE);
+            Log.i(TAG, STRING_PREF + ":" + stringValue);
+
+            mDefaultValues = mDefaultValues
+                            && floatValue == DEFAULT_FLOAT_VALUE
+                            && longValue == DEFAULT_LONG_VALUE
+                            && stringValue == DEFAULT_STRING_VALUE;
+        }
+
+        private void loadFile(String fileName) {
+            StringBuilder contents = new StringBuilder();
+            Scanner scanner = null;
+            try {
+                scanner = new Scanner(new File(getFilesDir(), fileName));
+                while (scanner.hasNext()) {
+                    contents.append(scanner.nextLine());
+                }
+                scanner.close();
+            } catch (FileNotFoundException e) {
+                Log.i(TAG, "Couldn't find test file but this may be fine...");
+            } finally {
+                if (scanner != null) {
+                    scanner.close();
+                }
+            }
+            String logString = contents.toString();
+            logString = logString.isEmpty() ? EMPTY_STRING_LOG : logString;
+            Log.i(TAG, fileName + ":" + logString);
+
+            mDefaultValues = mDefaultValues && contents.toString().isEmpty();
+        }
+
+        @Override
+        protected void onPostExecute(Void param) {
+            super.onPostExecute(param);
+
+            if (mDefaultValues && !mValuesWereGenerated) {
+                new GenerateValuesTask().execute();
+            } else {
+                Log.i(TAG, VALUES_LOADED_MESSAGE);
+            }
+        }
+    }
+
+    class GenerateValuesTask extends AsyncTask<Void, Void, Exception> {
+
+        @Override
+        protected Exception doInBackground(Void... params) {
+            Random random = new Random();
+            generatePreferenceGroup1(random);
+            generatePreferenceGroup2(random);
+            try {
+                generateTestFile(TEST_FILE_1, random);
+                generateTestFile(TEST_FILE_2, random);
+            } catch (FileNotFoundException e) {
+                return e;
+            }
+            return null;
+        }
+
+        private void generatePreferenceGroup1(Random random) {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
+            SharedPreferences.Editor editor = prefs.edit();
+            editor.putInt(INT_PREF, (random.nextInt(100) + 1));
+            editor.putBoolean(BOOL_PREF, random.nextBoolean());
+            editor.commit();
+        }
+
+        private void generatePreferenceGroup2(Random random) {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
+            SharedPreferences.Editor editor = prefs.edit();
+            editor.putFloat(FLOAT_PREF, random.nextFloat());
+            editor.putLong(LONG_PREF, random.nextLong());
+            editor.putString(STRING_PREF, "Random number " + (random.nextInt(100) + 1));
+            editor.commit();
+        }
+
+        private void generateTestFile(String fileName, Random random)
+                throws FileNotFoundException {
+            File file = new File(getFilesDir(), fileName);
+            PrintWriter writer = new PrintWriter(file);
+            writer.write("Random number " + (random.nextInt(100) + 1));
+            writer.close();
+        }
+
+        @Override
+        protected void onPostExecute(Exception exception) {
+            super.onPostExecute(exception);
+            mValuesWereGenerated = true;
+
+            if (exception != null) {
+                Log.e(TAG, "Couldn't generate test data...", exception);
+            } else {
+                BackupManager backupManager = new BackupManager(
+                        KeyValueBackupRandomDataActivity.this);
+                backupManager.dataChanged();
+
+                new LoadBackupItemsTask().execute();
+            }
+        }
+    }
+}
diff --git a/hostsidetests/backup/fullbackupapp/Android.mk b/hostsidetests/backup/fullbackupapp/Android.mk
new file mode 100644
index 0000000..46af984
--- /dev/null
+++ b/hostsidetests/backup/fullbackupapp/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 := CtsFullbackupApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/backup/fullbackupapp/AndroidManifest.xml b/hostsidetests/backup/fullbackupapp/AndroidManifest.xml
new file mode 100644
index 0000000..58f9306
--- /dev/null
+++ b/hostsidetests/backup/fullbackupapp/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?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.fullbackupapp">
+
+    <application android:label="FullbackupApp" >
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.cts.backup.fullbackupapp" />
+
+</manifest>
diff --git a/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java b/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java
new file mode 100644
index 0000000..7c3a6f6
--- /dev/null
+++ b/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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.fullbackupapp;
+
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+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 NoBackupFolderHostSideTest. 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 FullbackupTest {
+    public static final String TAG = "FullbackupCTSApp";
+    private static final int FILE_SIZE_BYTES = 1024 * 1024;
+
+    private Context mContext;
+
+    private File mNoBackupFile;
+    private File mNoBackupFile2;
+    private File mDoBackupFile;
+    private File mDoBackupFile2;
+
+    @Before
+    public void setUp() {
+        mContext = getTargetContext();
+        setupFiles();
+    }
+
+    private void setupFiles() {
+        // Files in the 'no_backup' directory. We expect these to not be backed up.
+        File noBackupDir = mContext.getNoBackupFilesDir();
+        File folderInNoBackup = new File(noBackupDir, "folder_not_to_backup");
+
+        mNoBackupFile = new File(noBackupDir, "file_not_backed_up");
+        mNoBackupFile2 = new File(folderInNoBackup, "file_not_backed_up2");
+
+        // Files in the normal files directory. These should be backed up and restored.
+        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();
+        checkNoFilesExist();
+
+        // Create test data
+        generateFiles();
+        checkAllFilesExist();
+
+        Log.d(TAG, "Test files created:");
+        Log.d(TAG, mNoBackupFile.getAbsolutePath());
+        Log.d(TAG, mNoBackupFile2.getAbsolutePath());
+        Log.d(TAG, mDoBackupFile.getAbsolutePath());
+        Log.d(TAG, mDoBackupFile2.getAbsolutePath());
+    }
+
+    @Test
+    public void deleteFilesAfterBackup() throws Exception {
+        // Make sure the test data exists first
+        checkAllFilesExist();
+
+        // Delete test data
+        deleteAllFiles();
+
+        // No there should be no files left
+        checkNoFilesExist();
+    }
+
+    @Test
+    public void checkRestoredFiles() throws Exception {
+        // After a restore, only files outside the 'no_backup' folder should exist
+        checkNoBackupFilesDoNotExist();
+        checkDoBackupFilesDoExist();
+    }
+
+    private void generateFiles() {
+        try {
+            // Add data to all the files we created
+            addData(mNoBackupFile);
+            addData(mNoBackupFile2);
+            addData(mDoBackupFile);
+            addData(mDoBackupFile2);
+            Log.d(TAG, "Files generated!");
+        } catch (IOException e) {
+            Log.e(TAG, "Unable to generate files", e);
+        }
+    }
+
+    private void deleteAllFiles() {
+        mNoBackupFile.delete();
+        mNoBackupFile2.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 checkAllFilesExist() {
+        assertTrue("File in 'no_backup' did not exist!", mNoBackupFile.exists());
+        assertTrue("File in folder inside 'no_backup' did not exist!", mNoBackupFile2.exists());
+        assertTrue("File in 'files' did not exist!", mDoBackupFile.exists());
+        assertTrue("File in folder inside 'files' did not exist!", mDoBackupFile2.exists());
+    }
+
+    private void checkNoFilesExist() {
+        assertFalse("File in 'no_backup' did exist!", mNoBackupFile.exists());
+        assertFalse("File in folder inside 'no_backup' did exist!", mNoBackupFile2.exists());
+        assertFalse("File in 'files' did exist!", mDoBackupFile.exists());
+        assertFalse("File in folder inside 'files' did exist!", mDoBackupFile2.exists());
+    }
+
+    private void checkNoBackupFilesDoNotExist() {
+        assertFalse("File in 'no_backup' did exist!", mNoBackupFile.exists());
+        assertFalse("File in folder inside 'no_backup' did exist!", mNoBackupFile2.exists());
+    }
+
+    private void checkDoBackupFilesDoExist() {
+        assertTrue("File in 'files' did not exist!", mDoBackupFile.exists());
+        assertTrue("File in folder inside 'files' did not exist!", mDoBackupFile2.exists());
+    }
+}
diff --git a/hostsidetests/backup/src/android/cts/backup/BackupRestoreHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/BackupRestoreHostSideTest.java
new file mode 100644
index 0000000..f156e68
--- /dev/null
+++ b/hostsidetests/backup/src/android/cts/backup/BackupRestoreHostSideTest.java
@@ -0,0 +1,242 @@
+/*
+ * 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.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.io.FileNotFoundException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test for checking that key/value backup and restore works correctly.
+ * It interacts with the app that generates random values and saves them in different shared
+ * preferences and files. The app uses BackupAgentHelper to do key/value backup of those values.
+ * The tests verifies that the values are restored after the app is uninstalled and reinstalled.
+ *
+ * NB: The tests uses "bmgr backupnow" for backup, which works on N+ devices.
+ */
+public class BackupRestoreHostSideTest extends BaseBackupHostSideTest {
+    /** The name of the APK of the app under test */
+    private static final String TEST_APP_APK = "CtsBackupRestoreDeviceApp.apk";
+
+    /** The package name of the APK */
+    private static final String PACKAGE_UNDER_TEST = "android.backup.cts.backuprestoreapp";
+
+    /** The class name of the main activity in the APK */
+    private static final String CLASS_UNDER_TEST = "KeyValueBackupRandomDataActivity";
+
+    /** The command to launch the main activity */
+    private static final String START_ACTIVITY_UNDER_TEST_COMMAND = String.format(
+            "am start -W -a android.intent.action.MAIN -n %s/%s.%s", PACKAGE_UNDER_TEST,
+            PACKAGE_UNDER_TEST,
+            CLASS_UNDER_TEST);
+
+    /** The command to clear the user data of the package */
+    private static final String CLEAR_DATA_IN_PACKAGE_UNDER_TEST_COMMAND = String.format(
+            "pm clear %s", PACKAGE_UNDER_TEST);
+
+    /**
+     * Time we wait before reading the logcat again if the message we want is not logged by the
+     * app yet.
+     */
+    private static final int SMALL_LOGCAT_DELAY_MS = 1000;
+
+    /**
+     * Message logged by the app after all the values were loaded from SharedPreferences and files.
+     */
+    private static final String VALUES_LOADED_MESSAGE = "ValuesLoaded";
+
+    /**
+     * Keys for various shared preferences and files saved/read by the app.
+     */
+    private static final String INT_PREF = "int-pref";
+    private static final String BOOL_PREF = "bool-pref";
+    private static final String FLOAT_PREF = "float-pref";
+    private static final String LONG_PREF = "long-pref";
+    private static final String STRING_PREF = "string-pref";
+    private static final String TEST_FILE_1 = "test-file-1";
+    private static final String TEST_FILE_2 = "test-file-2";
+
+    /** Number of the values saved/restored by the app (keys listed above) */
+    private static final int NUMBER_OF_VALUES = 7;
+
+    /**
+     * String equivalents of the default values of the shared preferences logged by the app.
+     * These values are logged by the app by default if it fails to generate or restore values.
+     */
+    private static final String DEFAULT_INT_STRING = Integer.toString(0);
+    private static final String DEFAULT_BOOL_STRING = Boolean.toString(false);
+    private static final String DEFAULT_FLOAT_STRING = Float.toString(0.0f);
+    private static final String DEFAULT_LONG_STRING = Long.toString(0L);
+    private static final String DEFAULT_STRING_STRING = "null";
+    private static final String DEFAULT_FILE_STRING = "empty";
+
+    private boolean mIsBackupSupported;
+    private boolean mWasBackupEnabled;
+    private String mOldTransport;
+
+    /**
+     * Map of the shared preferences/files values reported by the app.
+     * Format example: INT_PREF -> 17 (string, as found in the logcat).
+     */
+    private Map<String, String> mSavedValues;
+
+    public void testKeyValueBackupAndRestore() throws Exception {
+        // Clear app data if any
+        mDevice.executeShellCommand(CLEAR_DATA_IN_PACKAGE_UNDER_TEST_COMMAND);
+        // Clear logcat
+        mDevice.executeAdbCommand("logcat", "-c");
+        // Start the main activity of the app
+        mDevice.executeShellCommand(START_ACTIVITY_UNDER_TEST_COMMAND);
+
+        // The app will generate some random values onCreate. Save them to mSavedValues
+        saveDataValuesReportedByApp();
+
+        // If all the values are default, there is something wrong with the app
+        assertNotAllValuesAreDefault();
+
+        // Run backup
+        // TODO: make this compatible with N-, potentially by replacing 'backupnow' with 'run'.
+        String backupnowOutput = backupNow(PACKAGE_UNDER_TEST);
+
+        assertBackupIsSuccessful(PACKAGE_UNDER_TEST, backupnowOutput);
+
+        mDevice.uninstallPackage(PACKAGE_UNDER_TEST);
+
+        assertNull(super.installPackage(TEST_APP_APK));
+
+        mDevice.executeAdbCommand("logcat", "-c");
+
+        // Start the reinstalled app
+        mDevice.executeShellCommand(START_ACTIVITY_UNDER_TEST_COMMAND);
+
+        // If the app data was restored successfully, the app should not generate new values and
+        // the values reported by the app should match values saved in mSavedValues
+        assertValuesAreRestored();
+    }
+
+    /**
+     * Saves the data values reported by the app in {@code mSavedValues}.
+     */
+    private void saveDataValuesReportedByApp()
+            throws InterruptedException, DeviceNotAvailableException {
+        mSavedValues = readDataValuesFromLogcat();
+        assertEquals(NUMBER_OF_VALUES, mSavedValues.size());
+    }
+
+    /**
+     * Checks that at least some values in {@code mSavedValues} are different from corresponding
+     * default values.
+     */
+    private void assertNotAllValuesAreDefault() {
+        boolean allValuesAreDefault = mSavedValues.get(INT_PREF).equals(DEFAULT_INT_STRING)
+                && mSavedValues.get(BOOL_PREF).equals(DEFAULT_BOOL_STRING)
+                && mSavedValues.get(FLOAT_PREF).equals(DEFAULT_FLOAT_STRING)
+                && mSavedValues.get(LONG_PREF).equals(DEFAULT_LONG_STRING)
+                && mSavedValues.get(STRING_PREF).equals(DEFAULT_STRING_STRING)
+                && mSavedValues.get(TEST_FILE_1).equals(DEFAULT_FILE_STRING)
+                && mSavedValues.get(TEST_FILE_2).equals(DEFAULT_FILE_STRING);
+
+        assertFalse("The values were not changed from default.", allValuesAreDefault);
+    }
+
+    /**
+     * Reads the values logged by the app and verifies that they are the same as the ones we saved
+     * in {@code mSavedValues}.
+     */
+    private void assertValuesAreRestored()
+            throws InterruptedException, DeviceNotAvailableException {
+        Map<String, String> restoredValues = readDataValuesFromLogcat();
+
+        // Iterating through mSavedValues (vs. restoredValues) keyset to make sure all of the
+        // keys are reported in restored data
+        for (String dataType : mSavedValues.keySet()) {
+            assertEquals(mSavedValues.get(dataType), restoredValues.get(dataType));
+        }
+    }
+
+    /**
+     * Reads the values that app has reported via logcat and saves them in a map.
+     *
+     * The app logs the values once they are read from shared preferences or a file.
+     * If the values are default ones (i.e., it's the first run of the application), the app then
+     * generates random values and saves them in shared preferences or a file.
+     * Finally, the app reads the values from shared preferences or a file again and logs them.
+     * We are only interested in the final (generated or restored) values.
+     * The format of the log messages is "INT_PREF:17".
+     *
+     * @return Map of the values found in logcat.
+     */
+    private Map<String, String> readDataValuesFromLogcat()
+            throws InterruptedException, DeviceNotAvailableException {
+        Map<String, String> result = new HashMap<>();
+
+        long timeout = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(30);
+
+        // The app generates reads, generates and reads values in async tasks fired onCreate.
+        // It may take some time for all tasks to finish and for logs to appear, so we check logcat
+        // repeatedly until we read VALUES_LOADED_MESSAGE, which is the last message the app logs.
+        search:
+        while (timeout >= System.currentTimeMillis()) {
+            String logs = getLogcatForClass(CLASS_UNDER_TEST);
+
+            Scanner in = new Scanner(logs);
+            while (in.hasNextLine()) {
+                String line = in.nextLine();
+                // Filter by TAG.
+                if (line.startsWith("I/" + CLASS_UNDER_TEST)) {
+                    // Get rid of the TAG.
+                    String message = line.split(":", 2)[1].trim();
+
+                    // VALUES_LOADED_MESSAGE is logged by the app when all the values are loaded and
+                    // logged so we can stop expecting more lines at this point.
+                    if (message.equals(VALUES_LOADED_MESSAGE)) {
+                        break search;
+                    }
+
+                    // Values are logged by the app in the format "INT_PREF:17".
+                    String[] values = message.split(":");
+                    if (values.length == 2) {
+                        result.put(values[0], values[1]);
+                    }
+                }
+            }
+            in.close();
+
+            // In case the key has not been found, wait for the log to update before
+            // performing the next search.
+            Thread.sleep(SMALL_LOGCAT_DELAY_MS);
+        }
+        assertTrue("Timeout while reading the app values", timeout > System.currentTimeMillis());
+        return result;
+    }
+
+    /**
+     * Returns the logcat string with the tag {@param className} and clears everything else.
+     */
+    private String getLogcatForClass(String className) throws DeviceNotAvailableException {
+        return mDevice.executeAdbCommand("logcat", "-v", "brief", "-d", className + ":I", "*:S");
+    }
+}
diff --git a/hostsidetests/backup/src/android/cts/backup/BaseBackupHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/BaseBackupHostSideTest.java
new file mode 100644
index 0000000..a3c2467
--- /dev/null
+++ b/hostsidetests/backup/src/android/cts/backup/BaseBackupHostSideTest.java
@@ -0,0 +1,247 @@
+/*
+ * 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.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.cts.migration.MigrationHelper;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.FileNotFoundException;
+import java.util.Map;
+import java.util.HashSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.Scanner;
+
+/**
+ * Base class for CTS backup/restore hostside tests
+ */
+public abstract class BaseBackupHostSideTest extends DeviceTestCase implements IBuildReceiver {
+
+    /** Value of PackageManager.FEATURE_BACKUP */
+    private static final String FEATURE_BACKUP = "android.software.backup";
+
+    private static final String LOCAL_TRANSPORT =
+            "android/com.android.internal.backup.LocalTransport";
+
+    protected ITestDevice mDevice;
+
+    private boolean mIsBackupSupported;
+    private boolean mWasBackupEnabled;
+    private String mOldTransport;
+    private HashSet<String> mAvailableFeatures;
+    private IBuildInfo mCtsBuildInfo;
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuildInfo = buildInfo;
+    }
+
+    @Override
+    public void setUp() throws DeviceNotAvailableException, Exception {
+        mDevice = getDevice();
+        mIsBackupSupported = hasDeviceFeature(FEATURE_BACKUP);
+        assumeTrue(mIsBackupSupported);
+        // Enable backup and select local backup transport
+        assertTrue("LocalTransport should be available.", hasBackupTransport(LOCAL_TRANSPORT));
+        mWasBackupEnabled = enableBackup(true);
+        mOldTransport = setBackupTransport(LOCAL_TRANSPORT);
+        assertNotNull(mCtsBuildInfo);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        if (mIsBackupSupported) {
+            setBackupTransport(mOldTransport);
+            enableBackup(mWasBackupEnabled);
+        }
+    }
+
+    /**
+     * Execute shell command "bmgr backupnow <packageName>" and return output from this command.
+     */
+    protected String backupNow(String packageName) throws DeviceNotAvailableException {
+        return mDevice.executeShellCommand("bmgr backupnow " + packageName);
+    }
+
+    /**
+     * Execute shell command "bmgr restore <packageName>" and return output from this command.
+     */
+    protected String restore(String packageName) throws DeviceNotAvailableException {
+        return mDevice.executeShellCommand("bmgr restore " + packageName);
+    }
+
+    /**
+     * Copied from com.android.cts.net.HostsideNetworkTestCase.
+     */
+    protected void runDeviceTest(String packageName, String className, String testName)
+            throws DeviceNotAvailableException {
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName,
+                "android.support.test.runner.AndroidJUnitRunner", mDevice.getIDevice());
+
+        if (className != null) {
+            if (testName != null) {
+                testRunner.setMethodName(className, testName);
+            } else {
+                testRunner.setClassName(className);
+            }
+        }
+
+        final CollectingTestListener listener = new CollectingTestListener();
+        mDevice.runInstrumentationTests(testRunner, listener);
+
+        final TestRunResult result = listener.getCurrentRunResults();
+        if (result.isRunFailure()) {
+            throw new AssertionError("Failed to successfully run device tests for "
+                    + result.getName() + ": " + result.getRunFailureMessage());
+        }
+        if (result.getNumTests() == 0) {
+            throw new AssertionError("No tests were run on the device");
+        }
+        if (result.hasFailedTests()) {
+            // build a meaningful error message
+            StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+            for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+                result.getTestResults().entrySet()) {
+                if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+                    errorBuilder.append(resultEntry.getKey().toString());
+                    errorBuilder.append(":\n");
+                    errorBuilder.append(resultEntry.getValue().getStackTrace());
+                }
+            }
+            throw new AssertionError(errorBuilder.toString());
+        }
+    }
+
+    /**
+     * Parsing the output of "bmgr backupnow" command and checking that the package under test
+     * was backed up successfully.
+     *
+     * Expected format: "Package <packageName> with result: Success"
+     */
+    protected void assertBackupIsSuccessful(String packageName, String backupnowOutput) {
+        // Assert backup was successful.
+        Scanner in = new Scanner(backupnowOutput);
+        boolean success = false;
+        while (in.hasNextLine()) {
+            String line = in.nextLine();
+
+            if (line.contains(packageName)) {
+                String result = line.split(":")[1].trim();
+                if ("Success".equals(result)) {
+                    success = true;
+                }
+            }
+        }
+        in.close();
+        assertTrue(success);
+    }
+
+    protected String installPackage(String apkName)
+            throws DeviceNotAvailableException, FileNotFoundException {
+        return mDevice.installPackage(MigrationHelper.getTestFile(mCtsBuildInfo, apkName), true);
+    }
+
+    /**
+     * Parsing the output of "bmgr restore" command and checking that the package under test
+     * was restored successfully.
+     *
+     * Expected format: "restoreFinished: 0"
+     */
+    protected void assertRestoreIsSuccessful(String restoreOutput) {
+        assertTrue("Restore not successful", restoreOutput.contains("restoreFinished: 0"));
+    }
+
+    private boolean hasDeviceFeature(String requiredFeature) throws DeviceNotAvailableException {
+        if (mAvailableFeatures == null) {
+            String command = "pm list features";
+            String commandOutput = getDevice().executeShellCommand(command);
+            CLog.i("Output for command " + command + ": " + commandOutput);
+
+            // Extract the id of the new user.
+            mAvailableFeatures = new HashSet<>();
+            for (String feature: commandOutput.split("\\s+")) {
+                // Each line in the output of the command has the format "feature:{FEATURE_VALUE}".
+                String[] tokens = feature.split(":");
+                assertTrue("\"" + feature + "\" expected to have format feature:{FEATURE_VALUE}",
+                        tokens.length > 1);
+                assertEquals(feature, "feature", tokens[0]);
+                mAvailableFeatures.add(tokens[1]);
+            }
+        }
+        boolean result = mAvailableFeatures.contains(requiredFeature);
+        if (!result) {
+            CLog.d("Device doesn't have required feature "
+            + requiredFeature + ". Test won't run.");
+        }
+        return result;
+    }
+
+    // Copied over from BackupQuotaTest
+    private boolean enableBackup(boolean enable) throws Exception {
+        boolean previouslyEnabled;
+        String output = mDevice.executeShellCommand("bmgr enabled");
+        Pattern pattern = Pattern.compile("^Backup Manager currently (enabled|disabled)$");
+        Matcher matcher = pattern.matcher(output.trim());
+        if (matcher.find()) {
+            previouslyEnabled = "enabled".equals(matcher.group(1));
+        } else {
+            throw new RuntimeException("non-parsable output setting bmgr enabled: " + output);
+        }
+
+        mDevice.executeShellCommand("bmgr enable " + enable);
+        return previouslyEnabled;
+    }
+
+    // Copied over from BackupQuotaTest
+    private String setBackupTransport(String transport) throws Exception {
+        String output = mDevice.executeShellCommand("bmgr transport " + transport);
+        Pattern pattern = Pattern.compile("\\(formerly (.*)\\)$");
+        Matcher matcher = pattern.matcher(output);
+        if (matcher.find()) {
+            return matcher.group(1);
+        } else {
+            throw new RuntimeException("non-parsable output setting bmgr transport: " + output);
+        }
+    }
+
+    // Copied over from BackupQuotaTest
+    private boolean hasBackupTransport(String transport) throws Exception {
+        String output = mDevice.executeShellCommand("bmgr list transports");
+        for (String t : output.split(" ")) {
+            if (transport.equals(t.trim())) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/hostsidetests/backup/src/android/cts/backup/NoBackupFolderHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/NoBackupFolderHostSideTest.java
new file mode 100644
index 0000000..d51b46d
--- /dev/null
+++ b/hostsidetests/backup/src/android/cts/backup/NoBackupFolderHostSideTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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 org.junit.Assert.assertTrue;
+
+/**
+ * Test checking that files created by an app are restored successfully after a backup, but that
+ * files put in the folder provided by getNoBackupFilesDir() [files/no_backup] are NOT backed up.
+ *
+ * Invokes device side tests provided by android.cts.backup.fullbackupapp.FullbackupTest.
+ */
+public class NoBackupFolderHostSideTest extends BaseBackupHostSideTest {
+
+    private static final String TESTS_APP_NAME = "android.cts.backup.fullbackupapp";
+    private static final String DEVICE_TEST_CLASS_NAME = TESTS_APP_NAME + ".FullbackupTest";
+
+    public void testNoBackupFolder() throws Exception {
+        // Generate the files that are going to be backed up.
+        runDeviceTest(TESTS_APP_NAME, DEVICE_TEST_CLASS_NAME, "createFiles");
+
+        // Do a backup
+        String backupnowOutput = backupNow(TESTS_APP_NAME);
+
+        assertBackupIsSuccessful(TESTS_APP_NAME, backupnowOutput);
+
+        // Delete the files
+        runDeviceTest(TESTS_APP_NAME, DEVICE_TEST_CLASS_NAME, "deleteFilesAfterBackup");
+
+        // Do a restore
+        String restoreOutput = restore(TESTS_APP_NAME);
+
+        assertRestoreIsSuccessful(restoreOutput);
+
+        // Check that the right files were restored
+        runDeviceTest(TESTS_APP_NAME, DEVICE_TEST_CLASS_NAME, "checkRestoredFiles");
+    }
+}
diff --git a/tests/backup/src/android/backup/cts/BackupQuotaTest.java b/tests/backup/src/android/backup/cts/BackupQuotaTest.java
index 01c368a..bec28c7 100644
--- a/tests/backup/src/android/backup/cts/BackupQuotaTest.java
+++ b/tests/backup/src/android/backup/cts/BackupQuotaTest.java
@@ -46,14 +46,18 @@
 
     private static final int SMALL_LOGCAT_DELAY = 1000;
 
+    private boolean localTransportIsPresent;
     private boolean wasBackupEnabled;
     private String oldTransport;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        localTransportIsPresent = hasBackupTransport(LOCAL_TRANSPORT);
+        if (!localTransportIsPresent) {
+            return;
+        }
         // Enable backup and select local backup transport
-        assertTrue("LocalTransport should be available.", hasBackupTransport(LOCAL_TRANSPORT));
         wasBackupEnabled = enableBackup(true);
         oldTransport = setBackupTransport(LOCAL_TRANSPORT);
     }
@@ -61,12 +65,17 @@
     @Override
     protected void tearDown() throws Exception {
         // Return old transport
-        setBackupTransport(oldTransport);
-        enableBackup(wasBackupEnabled);
+        if (localTransportIsPresent) {
+            setBackupTransport(oldTransport);
+            enableBackup(wasBackupEnabled);
+        }
         super.tearDown();
     }
 
     public void testQuotaExceeded() throws Exception {
+        if (!localTransportIsPresent) {
+            return;
+        }
         exec("logcat --clear");
         exec("setprop log.tag." + APP_LOG_TAG +" VERBOSE");
         // Launch test app and create file exceeding limit for local transport