Merge "Skip UsbAccessory test on non-handheld devices" into marshmallow-cts-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index c0bd3f3..5f47671 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -78,6 +78,7 @@
cts_support_packages := \
CtsAccelerationTestStubs \
+ CtsBackupRestoreDeviceApp \
CtsAlarmClockService \
CtsAppTestStubs \
CtsAssistService \
@@ -231,6 +232,7 @@
# Host side only tests
cts_host_libraries := \
CtsAdbTests \
+ CtsBackupHostTestCases \
CtsAppSecurityTests \
CtsAtraceHostTestCases \
CtsCppToolsTestCases \
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index af80aa3..e17834f 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.verifier"
android:versionCode="5"
- android:versionName="6.0_r28">
+ android:versionName="6.0_r29">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23"/>
@@ -64,13 +64,9 @@
<application android:label="@string/app_name"
android:icon="@drawable/icon"
- android:backupAgent="VerifierBackupAgent"
android:debuggable="true"
android:largeHeap="true">
- <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" />
@@ -163,15 +159,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>
-
<activity android:name=".bluetooth.BluetoothTestActivity"
android:label="@string/bluetooth_test"
android:configChanges="keyboardHidden|orientation|screenSize">
@@ -458,8 +445,8 @@
<meta-data android:name="test_required_features" android:value="android.hardware.location.gps" />
</activity>
- <activity android:name=".net.ConnectivityScreenOffTestActivity"
- android:label="@string/network_screen_off_test">
+ <activity android:name=".net.ConnectivityBackgroundTestActivity"
+ android:label="@string/network_background_test">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.cts.intent.category.MANUAL_TEST" />
@@ -1399,7 +1386,7 @@
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_projection" />
<meta-data android:name="test_excluded_features"
- android:value="android.hardware.type.television:android.software.leanback" />
+ android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.automotive" />
</activity>
<service android:name=".projection.ProjectionService"
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/network_screen_off.xml b/apps/CtsVerifier/res/layout/network_background.xml
similarity index 96%
rename from apps/CtsVerifier/res/layout/network_screen_off.xml
rename to apps/CtsVerifier/res/layout/network_background.xml
index 5a2446d..50b64e3 100644
--- a/apps/CtsVerifier/res/layout/network_screen_off.xml
+++ b/apps/CtsVerifier/res/layout/network_background.xml
@@ -18,7 +18,7 @@
android:layout_height="match_parent">
<Button android:id="@+id/start_btn"
- android:text="@string/network_screen_off_test_start"
+ android:text="@string/network_background_test_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 346a8aa..cb853cb 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -52,35 +52,6 @@
<!-- Strings for ReportViewerActivity -->
<string name="report_viewer">Report Viewer</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_preferences">Preferences</string>
- <string name="bu_files">Files</string>
- <string name="bu_loading">Loading...</string>
- <string name="bu_generate">Generate Test Data</string>
- <string name="bu_generate_error">Error occurred while generating test data...</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>
- <string name="bu_settings">Settings</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
@@ -407,20 +378,20 @@
(for example, outside, or near a window)
and then press OK to run the automated tests.</string>
- <!-- Strings for net.ConnectivityScreenOffTestActivity -->
- <string name="network_screen_off_test">Network Connectivity Screen Off Test</string>
- <string name="network_screen_off_test_instructions">
+ <!-- Strings for ConnectivityBackgroundTestActivity -->
+ <string name="network_background_test">Network Background Connectivity Test</string>
+ <string name="network_background_test_instructions">
This test verifies that IPv6 network connectivity continues to work
- when the screen is off.\n\n
+ when the screen is off or is idle for some time.\n\n
1. Join a Wi-Fi network with IPv6 Internet access.\n
2. If the device has battery power, disconnect all power connectors.\n
- 3. Turn the screen off.\n
- 4. Wait until the screen turns on (it will take at least two minutes).\n
+ 3. Turn the screen off if possible.\n
+ 4. Wait until the screen turns on or the test result is displayed (it will take at least two minutes).\n
5. If necessary, unlock the device.\n
6. Please mark the test according to the result status indicated.\n
</string>
- <string name="network_screen_off_test_start">Start</string>
+ <string name="network_background_test_start">Start</string>
<!-- Strings for NfcTestActivity -->
<string name="nfc_test">NFC Test</string>
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 45e528f..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.RESULTS_CONTENT_URI,
- 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.RESULTS_CONTENT_URI, 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/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/apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityScreenOffTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityBackgroundTestActivity.java
similarity index 92%
rename from apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityScreenOffTestActivity.java
rename to apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityBackgroundTestActivity.java
index 6109893..496bbe4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityScreenOffTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityBackgroundTestActivity.java
@@ -30,7 +30,6 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.BatteryManager;
import android.os.Bundle;
@@ -59,7 +58,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
/**
- * A CTS Verifier test case for testing IPv6 network connectivity while the screen is off.
+ * A CTS Verifier test case for testing IPv6 network background connectivity.
*
* This tests that Wi-Fi implementations are compliant with section 7.4.5
* ("Minimum Network Capability") of the CDD. Specifically, it requires that: "unicast IPv6
@@ -72,12 +71,12 @@
* [2] The device must join an IPv6-capable network (basic IPv6 connectivity to an
* Internet resource is tested).
* [3] If the device has a battery, the device must be disconnected from any power source.
- * [4] The screen is put to sleep.
+ * [4] The screen is put to sleep if this feature supported.
* [5] After two minutes, another IPv6 connectivity test is performed.
*/
-public class ConnectivityScreenOffTestActivity extends PassFailButtons.Activity {
+public class ConnectivityBackgroundTestActivity extends PassFailButtons.Activity {
- private static final String TAG = ConnectivityScreenOffTestActivity.class.getSimpleName();
+ private static final String TAG = ConnectivityBackgroundTestActivity.class.getSimpleName();
private static final String V6CONN_URL = "https://ipv6.google.com/generate_204";
private static final String V6ADDR_URL = "https://google-ipv6test.appspot.com/ip.js?fmt=text";
@@ -102,7 +101,7 @@
private long mUserActivityTimeout = -1;
- public ConnectivityScreenOffTestActivity() {
+ public ConnectivityBackgroundTestActivity() {
mLock = new Object();
mState = new AppState();
@@ -132,12 +131,12 @@
}
private void setupUserInterface() {
- setContentView(R.layout.network_screen_off);
+ setContentView(R.layout.network_background);
setPassFailButtonClickListeners();
getPassButton().setEnabled(false);
setInfoResources(
- R.string.network_screen_off_test,
- R.string.network_screen_off_test_instructions,
+ R.string.network_background_test,
+ R.string.network_background_test_instructions,
-1);
mScrollView = (ScrollView) findViewById(R.id.scroll);
@@ -161,7 +160,8 @@
// Whether or not this device (currently) has a battery.
mWaitForPowerDisconnected =
- batteryInfo.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false) && !isLeanback();
+ batteryInfo.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false)
+ && !hasPersistentPower();
// Check if the device is already on battery power.
if (mWaitForPowerDisconnected) {
@@ -310,7 +310,8 @@
void setScreenOn() { mScreenOffTime = 0; }
void setScreenOff() { mScreenOffTime = SystemClock.elapsedRealtime(); }
- boolean validScreenStateForTesting() { return (mScreenOffTime > 0); }
+ boolean validScreenStateForTesting() {
+ return ((mScreenOffTime > 0) || !requiresScreenOffSupport()); }
void setPowerConnected() { mPowerDisconnectTime = 0; }
void setPowerDisconnected() { mPowerDisconnectTime = SystemClock.elapsedRealtime(); }
@@ -458,6 +459,13 @@
continue;
}
+ if ((localState.mScreenOffTime == 0) && !requiresScreenOffSupport()) {
+ // mScreenOffTime may never be initialized on some devices
+ // so do it now regardless of screen state to let the test start
+ // on devices where screen-off function support is not required
+ mState.setScreenOff();
+ }
+
if (mWaitForPowerDisconnected) {
final long delta = SystemClock.elapsedRealtime() - localState.mPowerDisconnectTime;
if (delta < MIN_POWER_DISCONNECT_MS) {
@@ -635,8 +643,19 @@
return new HttpResult(rcode, msg);
}
- private boolean isLeanback() {
- final PackageManager pm = this.getPackageManager();
- return (pm != null && pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK));
+ private boolean hasPersistentPower() {
+ // Cars and TVsets are always connected to the persistent power source
+ final PackageManager pm = getPackageManager();
+ return (pm != null
+ && (pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ || pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)));
}
+
+ private boolean requiresScreenOffSupport() {
+ // Cars may not support screen-off function
+ final PackageManager pm = getPackageManager();
+ return (pm != null
+ && !pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+ }
+
}
diff --git a/hostsidetests/backup/Android.mk b/hostsidetests/backup/Android.mk
new file mode 100644
index 0000000..36d39dd
--- /dev/null
+++ b/hostsidetests/backup/Android.mk
@@ -0,0 +1,38 @@
+# 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 := optional
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+# tag this module as a cts test artifact
+# LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_MODULE := CtsBackupHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+
+LOCAL_CTS_TEST_PACKAGE := android.host.backup
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/backup/app/Android.mk b/hostsidetests/backup/app/Android.mk
new file mode 100644
index 0000000..074452b
--- /dev/null
+++ b/hostsidetests/backup/app/Android.mk
@@ -0,0 +1,32 @@
+# 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_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsBackupRestoreDeviceApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_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/src/android/backup/cts/backup/BackupRestoreHostSideTest.java b/hostsidetests/backup/src/android/backup/cts/backup/BackupRestoreHostSideTest.java
new file mode 100644
index 0000000..d63ee8b
--- /dev/null
+++ b/hostsidetests/backup/src/android/backup/cts/backup/BackupRestoreHostSideTest.java
@@ -0,0 +1,377 @@
+/*
+ * 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.backup;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import java.io.FileNotFoundException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 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.
+ *
+ */
+public class BackupRestoreHostSideTest extends DeviceTestCase implements IBuildReceiver {
+
+ private static final String LOG_TAG = "BackupRestoreHostSideTest";
+
+ /** 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";
+
+ /** 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;
+ private ITestDevice mDevice;
+ private HashSet<String> mAvailableFeatures;
+ private CtsBuildHelper mBuild;
+
+ /**
+ * 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;
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ }
+
+ @Override
+ public void setUp() throws DeviceNotAvailableException, Exception {
+ mDevice = getDevice();
+ mIsBackupSupported = hasDeviceFeature(FEATURE_BACKUP);
+ if(mIsBackupSupported){
+ // Enable backup and select local backup transport
+ assertTrue("LocalTransport should be available.", hasBackupTransport(LOCAL_TRANSPORT));
+ mWasBackupEnabled = enableBackup(true);
+ mOldTransport = setBackupTransport(LOCAL_TRANSPORT);
+ assertNotNull(mBuild);
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (mIsBackupSupported) {
+ setBackupTransport(mOldTransport);
+ enableBackup(mWasBackupEnabled);
+ }
+ }
+
+ public void testKeyValueBackupAndRestore() throws Exception {
+ if(!mIsBackupSupported){
+ return;
+ }
+ assertNull(mDevice.installPackage(mBuild.getTestApp(TEST_APP_APK), true));
+ // 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
+ mDevice.executeShellCommand("bmgr run");
+
+ assertBackupFinished();
+
+ mDevice.uninstallPackage(PACKAGE_UNDER_TEST);
+
+ assertNull(mDevice.installPackage(mBuild.getTestApp(TEST_APP_APK), true));
+
+ 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);
+ }
+
+ /**
+ * Parsing logcat after "bmgr run" command and checking that the backup pass is finished before
+ * we move on to avoid a race condition.
+ *
+ * Expected format: "BackupManagerService: Backup pass finished"
+ */
+ private void assertBackupFinished() throws DeviceNotAvailableException {
+ boolean backupFinished = false;
+ long timeout = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(10 * 60); // 10 min
+ while (timeout >= System.currentTimeMillis() && !backupFinished) {
+ String logs = getLogcatForClass("BackupManagerService");
+
+ Scanner in = new Scanner(logs);
+ while (in.hasNextLine()) {
+ String line = in.nextLine();
+ if (line.contains("Backup pass finished")) {
+ backupFinished = true;
+ break;
+ }
+ }
+ in.close();
+ }
+
+ assertTrue("The backup pass never finished.", backupFinished);
+ }
+
+ /**
+ * 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");
+ }
+
+ // 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 {
+ CLog.i("In method hasBackupTransport");
+ String output = mDevice.executeShellCommand("bmgr list transports");
+ for (String t : output.split(" ")) {
+ if (transport.equals(t.trim())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ 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;
+ }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index c0f0277..f76910f 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
@Option(name="cts-install-path", description="the path to the cts installation to use")
private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
- public static final String CTS_BUILD_VERSION = "6.0_r28";
+ public static final String CTS_BUILD_VERSION = "6.0_r29";
public static final String CTS_PACKAGE = "com.android.cts.tradefed.testtype";
/**