Merge "DO NOT MERGE:Revert "Add dot and negative sign tests in VectorDrawable CTS"" into lmp-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 518de4b..2011b18 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -69,6 +69,7 @@
CtsDeviceTaskswitchingControl \
CtsDeviceUi \
CtsIntentReceiverApp \
+ CtsIntentSenderApp \
CtsManagedProfileApp \
CtsMonkeyApp \
CtsMonkeyApp2 \
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 3b74e52..2a236d1 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -481,7 +481,8 @@
<string name="snsr_wait_to_begin">Press \'Next\' to begin.</string>
<string name="snsr_on_complete_return">After completing the task, go back to this test.</string>
<string name="snsr_movement_expected">Movement was expected during the test. Found=%1$b.</string>
- <string name="snsr_sensor_feature_deactivation">Additionally, turn off any other features installed in the device, that register for sensors. Once you are done, you can continue the test.</string>
+ <string name="snsr_sensor_feature_deactivation">Turn off any special features installed in the
+ device that register for sensors. Once you are done, you can begin the test.</string>
<string name="snsr_setting_mode_request">You will be redirected to set \'%1$s\' to: %2$s.</string>
<string name="snsr_setting_mode_set">\'%1$s\' set to: %2$s.</string>
<string name="snsr_setting_mode_not_set">\'%1$s\' not set to: %2$s.</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
index 65a3a4d..82f8ae9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
@@ -32,8 +32,6 @@
*/
public class SensorFeaturesDeactivator {
- private boolean mInitialStateCaptured;
-
private final ISensorTestStateContainer mStateContainer;
private final SensorSettingContainer mAirplaneMode = new AirplaneModeSettingContainer();
@@ -64,10 +62,6 @@
}
public synchronized void requestToRestoreFeatures() throws InterruptedException {
- if (!isInitialStateCaptured()) {
- return;
- }
-
if (Thread.currentThread().isInterrupted()) {
// TODO: in the future, if the thread is interrupted, we might need to serialize the
// intermediate state we acquired so we can restore when we have a chance
@@ -82,21 +76,11 @@
}
private void captureInitialState() {
- if (mInitialStateCaptured) {
- return;
- }
-
mAirplaneMode.captureInitialState();
mScreenBrightnessMode.captureInitialState();
mAutoRotateScreenMode.captureInitialState();
mLocationMode.captureInitialState();
mKeepScreenOnMode.captureInitialState();
-
- mInitialStateCaptured = true;
- }
-
- private boolean isInitialStateCaptured() {
- return mInitialStateCaptured;
}
private class AirplaneModeSettingContainer extends SensorSettingContainer {
@@ -105,13 +89,15 @@
}
@Override
- protected int getSettingMode() {
+ protected int getSettingMode(int defaultValue) {
ContentResolver contentResolver = mStateContainer.getContentResolver();
// Settings.System.AIRPLANE_MODE_ON is deprecated in API 17
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
- return Settings.System.getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 0);
+ return Settings.System
+ .getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, defaultValue);
} else {
- return Settings.Global.getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
+ return Settings.Global
+ .getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, defaultValue);
}
}
}
@@ -122,11 +108,11 @@
}
@Override
- public int getSettingMode() {
+ public int getSettingMode(int defaultValue) {
return Settings.System.getInt(
mStateContainer.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
- Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+ defaultValue);
}
}
@@ -137,11 +123,11 @@
}
@Override
- protected int getSettingMode() {
+ protected int getSettingMode(int defaultValue) {
return Settings.System.getInt(
mStateContainer.getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION,
- 0 /* default */);
+ defaultValue);
}
}
@@ -152,11 +138,11 @@
}
@Override
- protected int getSettingMode() {
+ protected int getSettingMode(int defaultValue) {
return Settings.Global.getInt(
mStateContainer.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
- 0);
+ defaultValue);
}
}
@@ -166,11 +152,11 @@
}
@Override
- protected int getSettingMode() {
+ protected int getSettingMode(int defaultValue) {
return Settings.Secure.getInt(
mStateContainer.getContentResolver(),
Settings.Secure.LOCATION_MODE,
- Settings.Secure.LOCATION_MODE_OFF);
+ defaultValue);
}
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
index 82df502..2d44d8d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
@@ -24,12 +24,18 @@
* A helper class for {@link SensorFeaturesDeactivator}. It abstracts the responsibility of handling
* device settings that affect sensors.
*
- * This class is not thread safe. It is meant to be used only by {@link SensorFeaturesDeactivator}.
+ * This class is meant to be used only by {@link SensorFeaturesDeactivator}.
+ * To keep things simple, this class synchronizes access to its internal state on public methods.
+ * This approach is fine, because there is no need for concurrent access.
*/
abstract class SensorSettingContainer {
+ private static final int DEFAULT_SETTING_VALUE = -1;
+
private final String mAction;
private final int mSettingNameResId;
+ private boolean mInitialized;
+ private boolean mSettingAvailable;
private boolean mCapturedModeOn;
public SensorSettingContainer(String action, int settingNameResId) {
@@ -37,13 +43,21 @@
mSettingNameResId = settingNameResId;
}
- public void captureInitialState() {
+ public synchronized void captureInitialState() {
+ if (mInitialized) {
+ return;
+ }
+ mSettingAvailable = getSettingMode(DEFAULT_SETTING_VALUE) != DEFAULT_SETTING_VALUE;
mCapturedModeOn = getCurrentSettingMode();
+ mInitialized = true;
}
public synchronized void requestToSetMode(
ISensorTestStateContainer stateContainer,
- boolean modeOn) throws InterruptedException {
+ boolean modeOn) throws InterruptedException {
+ if (!isSettingAvailable()) {
+ return;
+ }
trySetMode(stateContainer, modeOn);
if (getCurrentSettingMode() != modeOn) {
String message = stateContainer.getString(
@@ -56,6 +70,9 @@
public synchronized void requestToResetMode(ISensorTestStateContainer stateContainer)
throws InterruptedException {
+ if (!isSettingAvailable()) {
+ return;
+ }
trySetMode(stateContainer, mCapturedModeOn);
}
@@ -75,12 +92,20 @@
}
private boolean getCurrentSettingMode() {
- return getSettingMode() != 0;
+ return getSettingMode(DEFAULT_SETTING_VALUE) != 0;
}
private String getSettingName(ISensorTestStateContainer stateContainer) {
return stateContainer.getString(mSettingNameResId);
}
- protected abstract int getSettingMode();
+ private boolean isSettingAvailable() {
+ if (!mInitialized) {
+ throw new IllegalStateException(
+ "Object must be initialized first by invoking #captureInitialState.");
+ }
+ return mSettingAvailable;
+ }
+
+ protected abstract int getSettingMode(int defaultValue);
}
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
index 17dc3f1..59f0752 100644
--- a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
@@ -22,12 +22,11 @@
import android.util.Log;
import java.io.BufferedReader;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.IOException;
import java.io.OutputStreamWriter;
-
/**
* Class to receive intents sent across profile boundaries, and read/write to content uri specified
* in these intents to test cross-profile content uris.
diff --git a/hostsidetests/devicepolicy/app/IntentSender/Android.mk b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
new file mode 100644
index 0000000..e45ec31
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2014 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_PACKAGE_NAME := CtsIntentSenderApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
new file mode 100644
index 0000000..070ef40
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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="com.android.cts.intent.sender">
+
+ <uses-sdk android:minSdkVersion="19" />
+
+ <permission
+ android:name="com.android.cts.intent.sender.permission.SAMPLE"
+ android:label="Sample Permission" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+
+ <activity android:name=".IntentSenderActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ </intent-filter>
+ </activity>
+
+ <provider
+ android:name="android.support.v4.content.FileProvider"
+ android:authorities="com.android.cts.intent.sender.fileprovider"
+ android:grantUriPermissions="true"
+ android:exported="false">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/filepaths" />
+ </provider>
+
+ <provider
+ android:name=".BasicContentProvider"
+ android:authorities="com.android.cts.intent.sender.provider"
+ android:grantUriPermissions="true"
+ android:exported="true"
+ android:permission="com.android.cts.intent.sender.permission.SAMPLE" />
+
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.cts.intent.sender"
+ android:label="Intent Sender CTS Tests" />
+
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/filepaths.xml b/hostsidetests/devicepolicy/app/IntentSender/res/xml/filepaths.xml
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/res/xml/filepaths.xml
rename to hostsidetests/devicepolicy/app/IntentSender/res/xml/filepaths.xml
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
similarity index 96%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
rename to hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
index f91d404..183ab9f 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.cts.managedprofile.crossprofilecontent;
+package com.android.cts.intent.sender;
import android.content.ContentProvider;
import android.content.ContentValues;
@@ -69,4 +69,3 @@
new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
}
}
-
diff --git a/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java
new file mode 100644
index 0000000..00fa6b7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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.intent.sender;
+
+import android.app.Activity;
+import android.content.Intent;
+
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+
+public class IntentSenderActivity extends Activity {
+
+ private final SynchronousQueue<Result> mResult = new SynchronousQueue<>();
+
+ public static class Result {
+ public final int resultCode;
+ public final Intent data;
+
+ public Result(int resultCode, Intent data) {
+ this.resultCode = resultCode;
+ this.data = data;
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == Activity.RESULT_OK) {
+ try {
+ mResult.offer(new Result(resultCode, data), 5, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public Intent getResult(Intent intent) throws Exception {
+ startActivityForResult(intent, 42);
+ final Result result = mResult.poll(30, TimeUnit.SECONDS);
+ return (result != null) ? result.data : null;
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
similarity index 76%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
rename to hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
index 85e7d1b..47de0da 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
@@ -13,30 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.cts.managedprofile.crossprofilecontent;
-import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+package com.android.cts.intent.sender;
-import android.app.admin.DevicePolicyManager;
import android.content.ClipData;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.net.Uri;
import android.support.v4.content.FileProvider;
-import android.test.ActivityInstrumentationTestCase2;
+import android.test.InstrumentationTestCase;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.IOException;
-public class CrossProfileContentTest extends
- ActivityInstrumentationTestCase2<IntentSenderActivity> {
+public class IntentSenderTest extends InstrumentationTestCase {
private static final String MESSAGE = "Sample Message";
@@ -49,35 +45,20 @@
private static final String TAG = "CrossProfileContentTest";
- private static final String BASIC_CONTENT_PROVIDER_AUTHORITY =
- "com.android.cts.managedprofile.basiccontentProvider";
-
-
- private DevicePolicyManager mDpm;
-
private Context mContext;
-
- public CrossProfileContentTest() {
- super(IntentSenderActivity.class);
- }
+ private IntentSenderActivity mActivity;
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getTargetContext();
- mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ACTION_READ_FROM_URI);
- intentFilter.addAction(ACTION_WRITE_TO_URI);
- intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
- mDpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
- DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+ mActivity = launchActivity(mContext.getPackageName(), IntentSenderActivity.class, null);
}
@Override
- protected void tearDown() throws Exception {
- mDpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+ public void tearDown() throws Exception {
super.tearDown();
+ mActivity.finish();
}
/**
@@ -85,14 +66,15 @@
* This intent will have, in the ClipData, a uri whose associated file stores a message.
* The receiver will read the message from the uri, and put it inside the result intent.
*/
- public void testReceiverCanRead() {
+ public void testReceiverCanRead() throws Exception {
Uri uri = getUriWithTextInFile("reading_test", MESSAGE);
assertTrue(uri != null);
Intent intent = new Intent(ACTION_READ_FROM_URI);
intent.setClipData(ClipData.newRawUri("", uri));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- Intent result = getActivity().getResultForIntent(intent);
- assertTrue(result != null);
+
+ final Intent result = mActivity.getResult(intent);
+ assertNotNull(result);
assertEquals(MESSAGE, result.getStringExtra("extra_response"));
}
@@ -102,7 +84,7 @@
* The receiver will read the message from the extra, and write it to the uri in
* the ClipData.
*/
- public void testReceiverCanWrite() {
+ public void testReceiverCanWrite() throws Exception {
// It's the receiver of the intent that should write to the uri, not us. So, for now, we
// write an empty string.
Uri uri = getUriWithTextInFile("writing_test", "");
@@ -112,19 +94,21 @@
intent.putExtra("extra_message", MESSAGE);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
- getActivity().getResultForIntent(intent);
+
+ mActivity.getResult(intent);
assertEquals(MESSAGE, getFirstLineFromUri(uri));
}
- public void testPersistablePermission() {
+ public void testPersistablePermission() throws Exception {
Uri uri = getUriWithTextInFile("persistable_test", MESSAGE);
grantPersistableReadPermission(uri);
// Now checking if the receiver can read this uri, without re-granting the read permission.
Intent intent = new Intent(ACTION_READ_FROM_URI);
intent.setClipData(ClipData.newRawUri("", uri));
- Intent result = getActivity().getResultForIntent(intent);
- assertTrue(result != null);
+
+ final Intent result = mActivity.getResult(intent);
+ assertNotNull(result);
assertEquals(MESSAGE, result.getStringExtra("extra_response"));
}
@@ -138,7 +122,7 @@
* uriNotGranted), to enforce that even if an app has permission to one uri of a
* ContentProvider, it still cannot access a uri it does not have access to.
*/
- public void testAppPermissionsDontWorkAcrossProfiles() {
+ public void testAppPermissionsDontWorkAcrossProfiles() throws Exception {
// The FileProvider does not allow to use app permissions. So we need to use another
// ContentProvider.
Uri uriGranted = getBasicContentProviderUri("uri_granted");
@@ -152,19 +136,41 @@
Intent notGrant = new Intent(ACTION_READ_FROM_URI);
notGrant.setClipData(ClipData.newRawUri("", uriNotGranted));
- Intent result = getActivity().getResultForIntent(notGrant);
- assertTrue(result != null);
+ final Intent result = mActivity.getResult(notGrant);
+ assertNotNull(result);
// The receiver did not have permission to read the uri. So it should have caught a security
// exception.
assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
}
- private void grantPersistableReadPermission(Uri uri) {
+ /**
+ * Ensure that sender is only able to send data that it has access to.
+ */
+ public void testSecurity() throws Exception {
+ // Pick a URI that neither of us have access to; it doens't matter if
+ // its missing, since we expect a SE before a FNFE.
+ final Uri uri = Uri.parse("content://media/external/images/media/10240");
+ final Intent intent = new Intent(ACTION_READ_FROM_URI);
+ intent.setClipData(ClipData.newRawUri("", uri));
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // We're expecting to run into a security exception
+ final Intent result = mActivity.getResult(intent);
+ if (result == null) {
+ // This is fine; probably of a SecurityException when off in the
+ // system somewhere.
+ } else {
+ // But if we somehow came through, make sure they threw.
+ assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
+ }
+ }
+
+ private void grantPersistableReadPermission(Uri uri) throws Exception {
Intent grantPersistable = new Intent(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
grantPersistable.setClipData(ClipData.newRawUri("", uri));
grantPersistable.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
- getActivity().getResultForIntent(grantPersistable);
+ mActivity.getResult(grantPersistable);
}
private Uri getBasicContentProviderUri(String path) {
@@ -172,7 +178,7 @@
// granting these uris to other apps, or these apps from trying to access these uris.
return new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
- .authority(BASIC_CONTENT_PROVIDER_AUTHORITY)
+ .authority("com.android.cts.intent.sender.provider")
.path(path)
.build();
}
@@ -191,7 +197,7 @@
Log.e(TAG, "Could not create file " + filename + " with text " + text);
return null;
}
- return FileProvider.getUriForFile(mContext, "com.android.cts.managedprofile.fileprovider",
+ return FileProvider.getUriForFile(mContext, "com.android.cts.intent.sender.fileprovider",
file);
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 56b3671..008ed38 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -19,9 +19,6 @@
<uses-sdk android:minSdkVersion="20"/>
- <permission android:name="com.android.cts.managedprofile.permission.SAMPLE"
- android:label="Sample Permission"/>
-
<application>
<uses-library android:name="android.test.runner" />
<receiver
@@ -65,11 +62,6 @@
<action android:name="com.android.cts.managedprofile.ACTION_TEST_ALL_ACTIVITY" />
</intent-filter>
</activity>
- <activity android:name=".crossprofilecontent.IntentSenderActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- </intent-filter>
- </activity>
<activity android:name=".UserRestrictionActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -77,22 +69,6 @@
</intent-filter>
</activity>
<activity android:name=".TestActivity" />
- <provider
- android:name="android.support.v4.content.FileProvider"
- android:authorities="com.android.cts.managedprofile.fileprovider"
- android:grantUriPermissions="true"
- android:exported="false">
- <meta-data
- android:name="android.support.FILE_PROVIDER_PATHS"
- android:resource="@xml/filepaths" />
- </provider>
- <provider
- android:name="com.android.cts.managedprofile.crossprofilecontent.BasicContentProvider"
- android:authorities="com.android.cts.managedprofile.basiccontentProvider"
- android:grantUriPermissions="true"
- android:exported="true"
- android:permission="com.android.cts.managedprofile.permission.SAMPLE"
- />
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/AllUsersActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AllUsersActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/AllUsersActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AllUsersActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ComponentDisablingActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ComponentDisablingActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ComponentDisablingActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ComponentDisablingActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java
new file mode 100644
index 0000000..9615991
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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.managedprofile;
+
+import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.test.AndroidTestCase;
+
+public class CrossProfileUtils extends AndroidTestCase {
+ private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
+
+ private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+
+ private static final String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+ "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+ public void addParentCanAccessManagedFilters() {
+ removeAllFilters();
+
+ final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_READ_FROM_URI);
+ intentFilter.addAction(ACTION_WRITE_TO_URI);
+ intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+ dpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+ DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+ }
+
+ public void addManagedCanAccessParentFilters() {
+ removeAllFilters();
+
+ final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_READ_FROM_URI);
+ intentFilter.addAction(ACTION_WRITE_TO_URI);
+ intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+ dpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+ DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
+ }
+
+ public void removeAllFilters() {
+ final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ dpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
similarity index 99%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
index 35f70be..b0e84ae 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.cts.managedprofile;
import android.app.Activity;
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserFilterSetterActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserFilterSetterActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserFilterSetterActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserFilterSetterActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
similarity index 99%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
index 7098d9e..40ff6c5 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.cts.managedprofile;
import android.app.admin.DevicePolicyManager;
@@ -55,7 +56,7 @@
public void testAddCrossProfileIntentFilter_all() {
assertEquals(2, mPackageManager.queryIntentActivities(
new Intent(AllUsersActivity.ACTION), /* flags = */ 0).size());
-
+
// If we used startActivity(), the user would have a disambiguation dialog presented which
// requires human intervention, so we won't be testing like that
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/TestActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/TestActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/TestActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/TestActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
deleted file mode 100644
index e4c8ddf..0000000
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 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.managedprofile.crossprofilecontent;
-
-import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.util.Log;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-public class IntentSenderActivity extends Activity {
-
- private CountDownLatch mLatch;
-
- private static final int WAIT_FOR_RESPONSE_TIMEOUT_SECONDS = 5;
-
- private Intent mResult;
-
- Intent getResultForIntent(Intent intent) {
- mLatch = new CountDownLatch(1);
- mResult = null;
- startActivityForResult(intent, 0);
- try {
- mLatch.await(WAIT_FOR_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- }
- return mResult;
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent result) {
- if (resultCode == Activity.RESULT_OK) {
- mResult = result;
- }
- mLatch.countDown();
- }
-}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 15c7725..544ddff 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -17,6 +17,7 @@
package com.android.cts.devicepolicy;
import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.testrunner.InstrumentationResultParser;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
@@ -26,11 +27,13 @@
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.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashSet;
@@ -74,6 +77,21 @@
installResult);
}
+ protected void installAppAsUser(String appFileName, int userId) throws FileNotFoundException,
+ DeviceNotAvailableException {
+ final ITestDevice device = getDevice();
+
+ final File apk = mCtsBuild.getTestApp(appFileName);
+ final String remotePath = "/data/local/tmp/" + apk.getName();
+ if (!device.pushFile(apk, remotePath)) {
+ throw new IllegalStateException("Failed to push " + apk);
+ }
+
+ final String result = device.executeShellCommand(
+ "pm install --user " + userId + " " + remotePath);
+ assertTrue(result, result.contains("\nSuccess"));
+ }
+
/** Initializes the user with the given id. This is required so that apps can run on it. */
protected void startUser(int userId) throws DeviceNotAvailableException {
String command = "am start-user " + userId;
@@ -135,7 +153,17 @@
protected boolean runDeviceTestsAsUser(
String pkgName, @Nullable String testClassName, int userId)
throws DeviceNotAvailableException {
- return runDeviceTests(pkgName, testClassName, null /*testMethodName*/, userId);
+ return runDeviceTestsAsUser(pkgName, testClassName, null, userId);
+ }
+
+ /** Returns true if the specified tests passed. Tests are run as given user. */
+ protected boolean runDeviceTestsAsUser(
+ String pkgName, @Nullable String testClassName, String testMethodName, int userId)
+ throws DeviceNotAvailableException {
+ if (testClassName.startsWith(".")) {
+ testClassName = pkgName + testClassName;
+ }
+ return runDeviceTests(pkgName, testClassName, testMethodName, userId);
}
private boolean runDeviceTests(String pkgName, @Nullable String testClassName,
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 88a3b70..6ece85c 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -28,6 +28,9 @@
private static final String MANAGED_PROFILE_PKG = "com.android.cts.managedprofile";
private static final String MANAGED_PROFILE_APK = "CtsManagedProfileApp.apk";
+ private static final String INTENT_SENDER_PKG = "com.android.cts.intent.sender";
+ private static final String INTENT_SENDER_APK = "CtsIntentSenderApp.apk";
+
private static final String INTENT_RECEIVER_PKG = "com.android.cts.intent.receiver";
private static final String INTENT_RECEIVER_APK = "CtsIntentReceiverApp.apk";
@@ -110,16 +113,30 @@
if (!mHasFeature) {
return;
}
+
try {
- installApp(INTENT_RECEIVER_APK);
+ getDevice().uninstallPackage(INTENT_SENDER_PKG);
+ getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+ installAppAsUser(INTENT_SENDER_APK, 0);
+ installAppAsUser(INTENT_RECEIVER_APK, mUserId);
- String command = "pm uninstall --user " + mUserId + " " + INTENT_RECEIVER_PKG;
- CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
- + getDevice().executeShellCommand(command));
+ // Test from parent to managed
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
+ "addManagedCanAccessParentFilters", mUserId));
+ assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".IntentSenderTest", 0));
- assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG,
- MANAGED_PROFILE_PKG + ".crossprofilecontent.CrossProfileContentTest", mUserId));
+ getDevice().uninstallPackage(INTENT_SENDER_PKG);
+ getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+ installAppAsUser(INTENT_SENDER_APK, mUserId);
+ installAppAsUser(INTENT_RECEIVER_APK, 0);
+
+ // Test from managed to parent
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
+ "addParentCanAccessManagedFilters", mUserId));
+ assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".IntentSenderTest", mUserId));
+
} finally {
+ getDevice().uninstallPackage(INTENT_SENDER_PKG);
getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
}
}
diff --git a/libs/commonutil/Android.mk b/libs/commonutil/Android.mk
new file mode 100644
index 0000000..9c131b0
--- /dev/null
+++ b/libs/commonutil/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include $(call all-subdir-makefiles)
+
+# ======================================================
+# Build a static host library for the AbiUtils
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := src/com/android/cts/util/AbiUtils.java
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := ctsabiutilslib
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/libs/commonutil/src/com/android/cts/util/AbiUtils.java b/libs/commonutil/src/com/android/cts/util/AbiUtils.java
index 4a34c6f..6f47d52 100644
--- a/libs/commonutil/src/com/android/cts/util/AbiUtils.java
+++ b/libs/commonutil/src/com/android/cts/util/AbiUtils.java
@@ -163,4 +163,22 @@
public static String getBitness(String name) {
return ABIS_32BIT.contains(name) ? "32" : "64";
}
+
+ /**
+ * @param abilistString A comma separated string containing abis.
+ * @return A List of Strings containing valid ABIs.
+ */
+ public static Set<String> parseAbiList(String unsupportedAbiDescription) {
+ Set<String> abiSet = new HashSet<>();
+ String[] descSegments = unsupportedAbiDescription.split(":");
+ if (descSegments.length == 2) {
+ for (String abi : descSegments[1].split(",")) {
+ String trimmedAbi = abi.trim();
+ if (isAbiSupportedByCts(trimmedAbi)) {
+ abiSet.add(trimmedAbi);
+ }
+ }
+ }
+ return abiSet;
+ }
}
diff --git a/tools/utils/Android.mk b/tools/utils/Android.mk
index 36081ca..0ba5cf4 100644
--- a/tools/utils/Android.mk
+++ b/tools/utils/Android.mk
@@ -25,6 +25,6 @@
LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
LOCAL_JAVA_LIBRARIES := junit
-LOCAL_STATIC_JAVA_LIBRARIES := vogarexpectlib
+LOCAL_STATIC_JAVA_LIBRARIES := ctsabiutilslib vogarexpectlib
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/utils/CollectAllTests.java b/tools/utils/CollectAllTests.java
index 367fb93..ed74824 100644
--- a/tools/utils/CollectAllTests.java
+++ b/tools/utils/CollectAllTests.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import com.android.cts.util.AbiUtils;
import org.junit.runner.RunWith;
import org.w3c.dom.Document;
@@ -20,6 +21,7 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import vogar.Expectation;
import vogar.ExpectationStore;
import java.io.BufferedReader;
@@ -61,9 +63,9 @@
private static final String TEST_TYPE = "LOCAL_TEST_TYPE :";
public static void main(String[] args) {
- if (args.length < 4 || args.length > 6) {
+ if (args.length < 5 || args.length > 7) {
System.err.println("usage: CollectAllTests <output-file> <manifest-file> <jar-file> "
- + "<java-package> [expectation-dir [makefile-file]]");
+ + "<java-package> <architecture> [expectation-dir [makefile-file]]");
if (args.length != 0) {
System.err.println("received:");
for (String arg : args) {
@@ -86,8 +88,14 @@
return;
}
}
- String libcoreExpectationDir = (args.length > 4) ? args[4] : null;
- String androidMakeFile = (args.length > 5) ? args[5] : null;
+ String architecture = args[4];
+ if (architecture == null || architecture.equals("")) {
+ System.err.println("Invalid architecture");
+ System.exit(1);
+ return;
+ }
+ String libcoreExpectationDir = (args.length > 5) ? args[5] : null;
+ String androidMakeFile = (args.length > 6) ? args[6] : null;
final TestType testType = TestType.getTestType(androidMakeFile);
@@ -207,7 +215,7 @@
try {
klass.getConstructor(new Class<?>[] { String.class } );
- addToTests(expectations, testCases, klass);
+ addToTests(expectations, architecture, testCases, klass);
continue;
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
@@ -218,7 +226,7 @@
try {
klass.getConstructor(new Class<?>[0]);
- addToTests(expectations, testCases, klass);
+ addToTests(expectations, architecture, testCases, klass);
continue;
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
@@ -356,6 +364,7 @@
}
private static void addToTests(ExpectationStore[] expectations,
+ String architecture,
Map<String,TestClass> testCases,
Class<?> testClass) {
Set<String> testNames = new HashSet<String>();
@@ -386,11 +395,12 @@
}
testNames.add(testName);
- addToTests(expectations, testCases, testClass, testName);
+ addToTests(expectations, architecture, testCases, testClass, testName);
}
}
private static void addToTests(ExpectationStore[] expectations,
+ String architecture,
Map<String,TestClass> testCases,
Class<?> test,
String testName) {
@@ -412,6 +422,10 @@
return;
}
+ Set<String> supportedAbis = VogarUtils.extractSupportedAbis(architecture,
+ expectations,
+ testClassName,
+ testName);
TestClass testClass;
if (testCases.containsKey(testClassName)) {
testClass = testCases.get(testClassName);
@@ -420,7 +434,8 @@
testCases.put(testClassName, testClass);
}
- testClass.mCases.add(new TestMethod(testName, "", "", knownFailure, false, false));
+ testClass.mCases.add(new TestMethod(testName, "", "", supportedAbis,
+ knownFailure, false, false));
}
private static boolean isJunit3Test(Class<?> klass) {
diff --git a/tools/utils/DescriptionGenerator.java b/tools/utils/DescriptionGenerator.java
index 607d2e5..09e1118 100644
--- a/tools/utils/DescriptionGenerator.java
+++ b/tools/utils/DescriptionGenerator.java
@@ -22,6 +22,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.Set;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -38,6 +39,7 @@
import org.w3c.dom.NodeList;
import vogar.ExpectationStore;
+import vogar.Expectation;
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.AnnotationTypeDoc;
@@ -82,11 +84,13 @@
static final String ATTRIBUTE_VALUE_FRAMEWORK = "Android 1.0";
static final String ATTRIBUTE_NAME = "name";
+ static final String ATTRIBUTE_ABIS = "abis";
static final String ATTRIBUTE_HOST_CONTROLLER = "HostController";
static final String XML_OUTPUT_PATH = "./description.xml";
static final String OUTPUT_PATH_OPTION = "-o";
+ static final String ARCHITECTURE_OPTION = "-a";
/**
* Start to parse the classes passed in by javadoc, and generate
@@ -103,12 +107,21 @@
}
String outputPath = XML_OUTPUT_PATH;
+ String architecture = null;
String[][] options = root.options();
for (String[] option : options) {
- if (option.length == 2 && option[0].equals(OUTPUT_PATH_OPTION)) {
- outputPath = option[1];
+ if (option.length == 2) {
+ if (option[0].equals(OUTPUT_PATH_OPTION)) {
+ outputPath = option[1];
+ } else if (option[0].equals(ARCHITECTURE_OPTION)) {
+ architecture = option[1];
+ }
}
}
+ if (architecture == null || architecture.equals("")) {
+ Log.e("Missing architecture!", null);
+ return false;
+ }
XMLGenerator xmlGenerator = null;
try {
@@ -128,7 +141,7 @@
for (ClassDoc clazz : classes) {
if ((!clazz.isAbstract()) && (isValidJUnitTestCase(clazz))) {
- xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore));
+ xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore, architecture));
}
}
@@ -420,6 +433,8 @@
Node caseNode = elem.appendChild(mDoc.createElement(TAG_TEST));
setAttribute(caseNode, ATTRIBUTE_NAME, caze.mName);
+ String abis = caze.mAbis.toString();
+ setAttribute(caseNode, ATTRIBUTE_ABIS, abis.substring(1, abis.length() - 1));
if ((caze.mController != null) && (caze.mController.length() != 0)) {
setAttribute(caseNode, ATTRIBUTE_HOST_CONTROLLER, caze.mController);
}
@@ -509,9 +524,9 @@
*
* @param clazz The specified ClassDoc.
*/
- TestClass(ClassDoc clazz, ExpectationStore expectationStore) {
+ TestClass(ClassDoc clazz, ExpectationStore expectationStore, String architecture) {
mName = clazz.toString();
- mCases = getTestMethods(expectationStore, clazz);
+ mCases = getTestMethods(expectationStore, architecture, clazz);
}
/**
@@ -520,7 +535,8 @@
* @param clazz The specified ClassDoc.
* @return A collection of TestMethod.
*/
- Collection<TestMethod> getTestMethods(ExpectationStore expectationStore, ClassDoc clazz) {
+ Collection<TestMethod> getTestMethods(ExpectationStore expectationStore,
+ String architecture, ClassDoc clazz) {
Collection<MethodDoc> methods = getAllMethods(clazz);
ArrayList<TestMethod> cases = new ArrayList<TestMethod>();
@@ -553,8 +569,13 @@
}
if (name.startsWith("test")) {
- cases.add(new TestMethod(name, method.commentText(), controller, knownFailure,
- isBroken, isSuppressed));
+ Expectation expectation = expectationStore.get(
+ VogarUtils.buildFullTestName(clazz.toString(), name));
+ Set<String> supportedAbis =
+ VogarUtils.extractSupportedAbis(architecture, expectation);
+ cases.add(new TestMethod(
+ name, method.commentText(), controller, supportedAbis,
+ knownFailure, isBroken, isSuppressed));
}
}
@@ -610,6 +631,7 @@
String mName;
String mDescription;
String mController;
+ Set<String> mAbis;
String mKnownFailure;
boolean mIsBroken;
boolean mIsSuppressed;
@@ -621,11 +643,12 @@
* @param description The description of the test case.
* @param knownFailure The reason of known failure.
*/
- TestMethod(String name, String description, String controller, String knownFailure,
- boolean isBroken, boolean isSuppressed) {
+ TestMethod(String name, String description, String controller, Set<String> abis,
+ String knownFailure, boolean isBroken, boolean isSuppressed) {
mName = name;
mDescription = description;
mController = controller;
+ mAbis = abis;
mKnownFailure = knownFailure;
mIsBroken = isBroken;
mIsSuppressed = isSuppressed;
diff --git a/tools/utils/VogarUtils.java b/tools/utils/VogarUtils.java
index c7070a5..5e8b944 100644
--- a/tools/utils/VogarUtils.java
+++ b/tools/utils/VogarUtils.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import com.android.cts.util.AbiUtils;
+
import vogar.Expectation;
import vogar.ExpectationStore;
import vogar.ModeId;
@@ -38,12 +40,26 @@
return false;
}
+ /**
+ * @return true iff the class/name is found in the vogar known failure list and it is not
+ * a known failure that is a result of an unsupported abi.
+ */
public static boolean isVogarKnownFailure(ExpectationStore expectationStore,
final String testClassName,
final String testMethodName) {
- String fullTestName = String.format("%s#%s", testClassName, testMethodName);
- return expectationStore != null
- && expectationStore.get(fullTestName) != Expectation.SUCCESS;
+ if (expectationStore == null) {
+ return false;
+ }
+ String fullTestName = buildFullTestName(testClassName, testMethodName);
+ Expectation expectation = expectationStore.get(fullTestName);
+ if (expectation == Expectation.SUCCESS) {
+ return false;
+ }
+
+ String description = expectation.getDescription();
+ boolean foundAbi = AbiUtils.parseAbiList(description).size() > 0;
+
+ return expectation != Expectation.SUCCESS && !foundAbi;
}
public static ExpectationStore provideExpectationStore(String dir) throws IOException {
@@ -67,4 +83,49 @@
}
return expectSet;
}
+
+ /** @return the test name in the form of com.android.myclass.TestClass#testMyMethod */
+ public static String buildFullTestName(String testClass, String testMethodName) {
+ return String.format("%s#%s", testClass, testMethodName);
+ }
+
+ /**
+ * This method looks in the description field of the Vogar entry for the ABI_LIST_MARKER
+ * and returns the list of abis found there.
+ *
+ * @return The Set of supported abis parsed from the {@code expectation}'s description.
+ */
+ public static Set<String> extractSupportedAbis(String architecture, Expectation expectation) {
+ Set<String> supportedAbiSet = AbiUtils.getAbisForArch(architecture);
+ if (expectation == null || expectation.getDescription().isEmpty()) {
+ // Include all abis since there was no limitation found in the description
+ return supportedAbiSet;
+ }
+
+ // Remove any abis that are not supported for the test.
+ supportedAbiSet.removeAll(AbiUtils.parseAbiList(expectation.getDescription()));
+
+ return supportedAbiSet;
+ }
+
+ /**
+ * Determine the correct set of ABIs for the given className/testName.
+ *
+ * @return the set of ABIs that can be expected to pass for the given combination of
+ * {@code architecture}, {@code className} and {@code testName}.
+ */
+ public static Set<String> extractSupportedAbis(String architecture,
+ ExpectationStore[] expectationStores,
+ String className,
+ String testName) {
+
+ String fullTestName = VogarUtils.buildFullTestName(className, testName);
+ Set<String> supportedAbiSet = AbiUtils.getAbisForArch(architecture);
+ for (ExpectationStore expectationStore : expectationStores) {
+ Expectation expectation = expectationStore.get(fullTestName);
+ supportedAbiSet.retainAll(extractSupportedAbis(architecture, expectation));
+ }
+
+ return supportedAbiSet;
+ }
}