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