Merge "Test to verify legacy a11y service request a11y button API"
diff --git a/apps/CameraITS/tests/scene1_1/test_burst_sameness_manual.py b/apps/CameraITS/tests/scene1_1/test_burst_sameness_manual.py
index 92239db..c82039f 100644
--- a/apps/CameraITS/tests/scene1_1/test_burst_sameness_manual.py
+++ b/apps/CameraITS/tests/scene1_1/test_burst_sameness_manual.py
@@ -23,12 +23,14 @@
import matplotlib.pyplot
import numpy
+API_LEVEL_30 = 30
BURST_LEN = 50
BURSTS = 5
COLORS = ["R", "G", "B"]
FRAMES = BURST_LEN * BURSTS
NAME = os.path.basename(__file__).split(".")[0]
SPREAD_THRESH = 0.03
+SPREAD_THRESH_API_LEVEL_30 = 0.02
def main():
@@ -91,13 +93,18 @@
pylab.ylabel("RGB avg [0, 1]")
matplotlib.pyplot.savefig("%s_plot_means.png" % (NAME))
+ # determine spread_thresh
+ spread_thresh = SPREAD_THRESH
+ if its.device.get_first_api_level() >= API_LEVEL_30:
+ spread_thresh = SPREAD_THRESH_API_LEVEL_30
+
# PASS/FAIL based on center patch similarity.
for plane, means in enumerate([r_means, g_means, b_means]):
spread = max(means) - min(means)
- msg = "%s spread: %.5f, SPREAD_THRESH: %.3f" % (
- COLORS[plane], spread, SPREAD_THRESH)
+ msg = "%s spread: %.5f, spread_thresh: %.3f" % (
+ COLORS[plane], spread, spread_thresh)
print msg
- assert spread < SPREAD_THRESH, msg
+ assert spread < spread_thresh, msg
if __name__ == "__main__":
main()
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index f4d9490..ab6cf64 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -872,7 +872,7 @@
<string name="multinetwork_connectivity_test_all_prereq_1">Looks like your device does not support telephony or mobile data. If yes, you can mark test passed and proceed.</string>
<string name="multinetwork_connectivity_test_all_prereq_2">Need mobile data to proceed. Please insert a mobile data capable sim and repeat the test. By marking test as passed, you acknowledge that the device cannot do mobile data.</string>
<string name="multinetwork_status_wifi_connectivity_failed">Wi-Fi connectivity failed.</string>
- <string name="multinetwork_connectivity_overlay_permission_message">This test requires the CTS verifier to have the system overlay permission, please enable it in the next screen.</string>
+ <string name="multinetwork_connectivity_overlay_permission_message">This test requires the CTS verifier to have the system overlay permission, please locate CTS Verifier app in the next screen, then enable it.</string>
<string name="multinetwork_connectivity_overlay_permission_positive">Settings</string>
<string name="multinetwork_connectivity_overlay_permission_negative">Cancel</string>
<!-- Strings for NfcTestActivity -->
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
index 10f94c8..7a935a9 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
@@ -36,7 +36,7 @@
}
public static UiObject2 waitFindObject(BySelector selector) throws UiObjectNotFoundException {
- return waitFindObject(selector, 100_000);
+ return waitFindObject(selector, 100_00);
}
public static UiObject2 waitFindObject(BySelector selector, long timeoutMs)
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml
index ada3d19..e5300ab 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml
@@ -2,6 +2,7 @@
<resources>
<string name="Permissions">Permissions</string>
<string name="Deny">Deny</string>
+ <string name="Ask">Ask every time</string>
<string name="Allow">Allow</string>
<string name="AllowAll">Allow all the time</string>
</resources>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml
index ada3d19..e5300ab 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml
@@ -2,6 +2,7 @@
<resources>
<string name="Permissions">Permissions</string>
<string name="Deny">Deny</string>
+ <string name="Ask">Ask every time</string>
<string name="Allow">Allow</string>
<string name="AllowAll">Allow all the time</string>
</resources>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
index c2689ee..7fbb58a5 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
@@ -90,6 +90,10 @@
private static final long RETRY_TIMEOUT = 10 * GLOBAL_TIMEOUT_MILLIS;
private static final String LOG_TAG = "BasePermissionsTest";
+ private static final int STATE_ALLOWED = 0;
+ private static final int STATE_DENIED = 1;
+ private static final int STATE_DENIED_WITH_PREJUDICE = 2;
+
private static Map<String, String> sPermissionToLabelResNameMap = new ArrayMap<>();
private Context mContext;
@@ -380,7 +384,7 @@
}
protected void grantPermissions(String[] permissions) throws Exception {
- setPermissionGrantState(permissions, true, false);
+ setPermissionGrantState(permissions, STATE_ALLOWED, false);
}
protected void revokePermission(String permission) throws Exception {
@@ -388,7 +392,7 @@
}
protected void revokePermissions(String[] permissions, boolean legacyApp) throws Exception {
- setPermissionGrantState(permissions, false, legacyApp);
+ setPermissionGrantState(permissions, STATE_DENIED, legacyApp);
}
private void scrollToBottom() throws Exception {
@@ -401,7 +405,7 @@
}
}
- private void setPermissionGrantState(String[] permissions, boolean granted,
+ private void setPermissionGrantState(String[] permissions, int state,
boolean legacyApp) throws Exception {
ExceptionUtils.wrappingExceptions(UiDumpUtils::wrapWithUiDump, () -> {
getUiDevice().pressBack();
@@ -445,36 +449,49 @@
waitForIdle();
}
- final boolean wasGranted = isTv() ? false : !waitFindObject(byText(R.string.Deny)).isChecked();
- // TV does not use checked state to represent granted state.
- if (granted != wasGranted || isTv()) {
- // Toggle the permission
-
- if (isTv()) {
- waitFindObject(By.text(permissionLabel)).click();
- } else if (granted) {
- waitFindObject(byText(R.string.Allow)).click();
- } else {
- waitFindObject(byText(R.string.Deny)).click();
+ final boolean wasGranted = isTv() ? false : !(waitFindObject(byText(R.string.Deny)).isChecked() || waitFindObject(byText(R.string.Ask)).isChecked());
+ boolean alreadyChecked = false;
+ if (isTv()) {
+ waitFindObject(By.text(permissionLabel)).click();
+ } else if (state == STATE_ALLOWED) {
+ UiObject2 object = waitFindObject(byText(R.string.Allow));
+ alreadyChecked = object.isChecked();
+ if (!alreadyChecked) {
+ object.click();
}
+ } else if (state == STATE_DENIED){
+ UiObject2 object = waitFindObject(byText(R.string.Ask));
+ alreadyChecked = object.isChecked();
+ if (!alreadyChecked) {
+ object.click();
+ }
+ } else if (state == STATE_DENIED_WITH_PREJUDICE) {
+ UiObject2 object = waitFindObject(byText(R.string.Deny));
+ alreadyChecked = object.isChecked();
+ if (!alreadyChecked) {
+ object.click();
+ }
+ }
+ if (alreadyChecked) {
+ continue;
+ }
+ waitForIdle();
+
+ if (wasGranted && legacyApp) {
+ scrollToBottom();
+ Context context = getInstrumentation().getContext();
+ String packageName = context.getPackageManager()
+ .getPermissionControllerPackageName();
+ String resIdName = "com.android.permissioncontroller"
+ + ":string/grant_dialog_button_deny_anyway";
+ Resources resources = context
+ .createPackageContext(packageName, 0).getResources();
+ final int confirmResId = resources.getIdentifier(resIdName, null, null);
+ String confirmTitle = resources.getString(confirmResId);
+
+ waitFindObject(byTextStartsWithCaseInsensitive(confirmTitle))
+ .click();
waitForIdle();
-
- if (wasGranted && legacyApp) {
- scrollToBottom();
- Context context = getInstrumentation().getContext();
- String packageName = context.getPackageManager()
- .getPermissionControllerPackageName();
- String resIdName = "com.android.permissioncontroller"
- + ":string/grant_dialog_button_deny_anyway";
- Resources resources = context
- .createPackageContext(packageName, 0).getResources();
- final int confirmResId = resources.getIdentifier(resIdName, null, null);
- String confirmTitle = resources.getString(confirmResId);
-
- waitFindObject(byTextStartsWithCaseInsensitive(confirmTitle))
- .click();
- waitForIdle();
- }
}
if (!isTv()) {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AdbProvisioningTests.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AdbProvisioningTests.java
index 8afcee6..cd19f68 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AdbProvisioningTests.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AdbProvisioningTests.java
@@ -33,10 +33,10 @@
@Override
public void setUp() throws Exception {
- super.setUp();
if (!mHasFeature) {
return;
}
+ super.setUp();
installAppAsUser(DEVICE_ADMIN_APK, mPrimaryUserId);
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index c6a3b39..a7f9639 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -106,6 +106,11 @@
*/
private static final long USER_REMOVE_WAIT = TimeUnit.SECONDS.toMillis(5);
+ /**
+ * The amount of milliseconds to wait for the switch user calls in {@link #tearDown}.
+ */
+ private static final long USER_SWITCH_WAIT = TimeUnit.SECONDS.toMillis(5);
+
// From the UserInfo class
protected static final int FLAG_GUEST = 0x00000004;
protected static final int FLAG_EPHEMERAL = 0x00000100;
@@ -136,6 +141,9 @@
protected boolean mHasFeature;
protected int mPrimaryUserId;
+ /** Record the initial user ID. */
+ protected int mInitialUserId;
+
/** Whether multi-user is supported. */
protected boolean mSupportsMultiUser;
@@ -175,6 +183,11 @@
mFixedUsers = new ArrayList<>();
mPrimaryUserId = getPrimaryUser();
+
+ // Set the value of initial user ID calls in {@link #setUp}.
+ if(mSupportsMultiUser) {
+ mInitialUserId = getDevice().getCurrentUser();
+ }
mFixedUsers.add(mPrimaryUserId);
if (mPrimaryUserId != USER_SYSTEM) {
mFixedUsers.add(USER_SYSTEM);
@@ -207,7 +220,11 @@
getDevice().executeShellCommand("settings put global verifier_verify_adb_installs "
+ mPackageVerifier);
removeOwners();
- switchUser(USER_SYSTEM);
+
+ // Switch back to initial user.
+ if (mSupportsMultiUser && getDevice().getCurrentUser() != mInitialUserId) {
+ switchUser(mInitialUserId);
+ }
removeTestUsers();
removeTestPackages();
}
@@ -277,7 +294,15 @@
*/
protected void switchUser(int userId) throws Exception {
// TODO Move this logic to ITestDevice
+ int retries = 10;
executeShellCommand("am switch-user " + userId);
+ while (getDevice().getCurrentUser() != userId && (--retries) >= 0) {
+ // am switch-user can be ignored if a previous user-switching operation
+ // is still in progress. In this case, sleep a bit and then retry
+ Thread.sleep(USER_SWITCH_WAIT);
+ executeShellCommand("am switch-user " + userId);
+ }
+ assertTrue("Failed to switch user after multiple retries", getDevice().getCurrentUser() == userId);
}
protected int getMaxNumberOfUsersSupported() throws DeviceNotAvailableException {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index e65627e..c27247f 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -2112,7 +2112,7 @@
* Start SimpleActivity synchronously in a particular user.
*/
protected void startSimpleActivityAsUser(int userId) throws Exception {
- installAppAsUser(TEST_APP_APK, userId);
+ installAppAsUser(TEST_APP_APK, /* grantPermissions */ true, /* dontKillApp */ true, userId);
startActivityAsUser(userId, TEST_APP_PKG, TEST_APP_PKG + ".SimpleActivity");
}
diff --git a/hostsidetests/dumpsys/AndroidTest.xml b/hostsidetests/dumpsys/AndroidTest.xml
index 11ab26f..b6d0270 100644
--- a/hostsidetests/dumpsys/AndroidTest.xml
+++ b/hostsidetests/dumpsys/AndroidTest.xml
@@ -19,6 +19,7 @@
<!-- This module tests system service dumps, which is irrelevant for Instant Apps. -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest">
<option name="jar" value="CtsDumpsysHostTestCases.jar" />
</test>
diff --git a/hostsidetests/hdmicec/Android.bp b/hostsidetests/hdmicec/Android.bp
index ca649d2..0fa3a6a 100644
--- a/hostsidetests/hdmicec/Android.bp
+++ b/hostsidetests/hdmicec/Android.bp
@@ -27,4 +27,7 @@
"tradefed",
"compatibility-host-util",
],
+ data: [
+ ":HdmiCecKeyEventCaptureApp",
+ ],
}
diff --git a/hostsidetests/hdmicec/AndroidTest.xml b/hostsidetests/hdmicec/AndroidTest.xml
index 0dfb7ec..2b1390a 100644
--- a/hostsidetests/hdmicec/AndroidTest.xml
+++ b/hostsidetests/hdmicec/AndroidTest.xml
@@ -19,6 +19,10 @@
<!-- Instant apps for TV is not supported. -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="HdmiCecKeyEventCaptureApp.apk" />
+ </target_preparer>
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsHdmiCecHostTestCases.jar" />
</test>
diff --git a/hostsidetests/hdmicec/app/Android.bp b/hostsidetests/hdmicec/app/Android.bp
new file mode 100644
index 0000000..910aa30
--- /dev/null
+++ b/hostsidetests/hdmicec/app/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2019 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.
+
+android_test_helper_app {
+ name: "HdmiCecKeyEventCaptureApp",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/hdmicec/app/AndroidManifest.xml b/hostsidetests/hdmicec/app/AndroidManifest.xml
new file mode 100644
index 0000000..ce9fff7
--- /dev/null
+++ b/hostsidetests/hdmicec/app/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.hdmicec.app">
+ <uses-feature android:name="android.software.leanback"
+ android:required="false" />
+ <application >
+ <activity android:name=".HdmiCecKeyEventCapture" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java
new file mode 100644
index 0000000..63736bf
--- /dev/null
+++ b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 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.hdmicec.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Gravity;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TableRow;
+import android.widget.TextView;
+
+import java.lang.Override;
+
+/**
+ * A simple app that captures the key press events and logs them.
+ */
+public class HdmiCecKeyEventCapture extends Activity {
+
+ private static final String TAG = HdmiCecKeyEventCapture.class.getSimpleName();
+ private TextView text;
+ private boolean longPressed = false;
+
+ static final String LONG_PRESS_PREFIX = "Long press ";
+ static final String SHORT_PRESS_PREFIX = "Short press ";
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ ScrollView sv = new ScrollView(this);
+ LinearLayout layout = new LinearLayout(this);
+ TableRow.LayoutParams layoutParams =
+ new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,
+ TableRow.LayoutParams.WRAP_CONTENT, 1.0f);
+ text = new TextView(this);
+ text.setGravity(Gravity.CENTER);
+ text.setText("No key pressed!");
+ text.setLayoutParams(layoutParams);
+ layout.addView(text);
+ this.setContentView(layout);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ event.startTracking();
+ return true;
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+
+ text.setText((longPressed ? "Long press " : "Short press ") +
+ event.keyCodeToString(keyCode));
+
+ Log.d(TAG, event.toString());
+ Log.i(TAG, (longPressed ? "Long press " : "Short press ") + event.keyCodeToString(keyCode));
+
+ longPressed = false;
+ return true;
+ }
+
+ @Override
+ public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ longPressed = true;
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/CecDevice.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/CecDevice.java
index 51884df..6eb3691 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/CecDevice.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/CecDevice.java
@@ -22,6 +22,7 @@
public enum CecDevice {
TV(0x0),
PLAYBACK_1(0x4),
+ AUDIO_SYSTEM(0x5),
PLAYBACK_2(0x8),
PLAYBACK_3(0x9),
PLAYBACK_4(0xb),
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/CecMessage.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/CecMessage.java
index aad9821..7c95f7e 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/CecMessage.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/CecMessage.java
@@ -23,10 +23,18 @@
FEATURE_ABORT(0x00),
TEXT_VIEW_ON(0x0d),
STANDBY(0x36),
+ USER_CONTROL_PRESSED(0x44),
+ USER_CONTROL_RELEASED(0x45),
+ GIVE_OSD_NAME(0x46),
+ SET_OSD_NAME(0x47),
+ GIVE_SYSTEM_AUDIO_MODE_STATUS(0x7d),
ACTIVE_SOURCE(0x82),
GIVE_PHYSICAL_ADDRESS(0x83),
REPORT_PHYSICAL_ADDRESS(0x84),
REQUEST_ACTIVE_SOURCE(0x85),
+ SET_STREAM_PATH(0x86),
+ DEVICE_VENDOR_ID(0x87),
+ GIVE_DEVICE_VENDOR_ID(0x8c),
GIVE_POWER_STATUS(0x8f),
REPORT_POWER_STATUS(0x90),
GET_MENU_LANGUAGE(0x91),
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
index 3c64588..f4c662d 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
@@ -28,6 +28,7 @@
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
+import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -45,6 +46,7 @@
private static final int DEFAULT_TIMEOUT = 20000;
private static final String HDMI_CEC_FEATURE = "feature:android.hardware.hdmi.cec";
private static final int HEXADECIMAL_RADIX = 16;
+ private static final int BUFFER_SIZE = 1024;
private Process mCecClient;
private BufferedWriter mOutputConsole;
@@ -105,7 +107,7 @@
mCecClientInitialised = true;
if (checkConsoleOutput(CecClientMessage.CLIENT_CONSOLE_READY + "", MILLISECONDS_TO_READY)) {
mOutputConsole = new BufferedWriter(
- new OutputStreamWriter(mCecClient.getOutputStream()));
+ new OutputStreamWriter(mCecClient.getOutputStream()), BUFFER_SIZE);
return;
}
@@ -153,12 +155,42 @@
* the cec-communication channel with the appended params.
*/
public void sendCecMessage(CecDevice source, CecDevice destination,
- CecMessage message, String params) throws Exception {
+ CecMessage message, String params) throws Exception {
checkCecClient();
mOutputConsole.write("tx " + source + destination + ":" + message + params);
mOutputConsole.flush();
}
+ /**
+ * Sends a <USER_CONTROL_PRESSED> and <USER_CONTROL_RELEASED> from TV to target device
+ * through the output console of the cec-communication channel with the mentioned keycode.
+ */
+ public void sendUserControlPressAndRelease(int keycode, boolean holdKey) throws Exception {
+ checkCecClient();
+ String key = String.format("%02x", keycode);
+ String command = "tx " + CecDevice.TV + CecDevice.PLAYBACK_1 + ":" +
+ CecMessage.USER_CONTROL_PRESSED + ":" + key;
+
+ if (holdKey) {
+ /* Repeat once between 200ms and 450ms for at least 5 seconds. Since message will be
+ * sent once later, send 16 times in loop every 300ms. */
+ int repeat = 16;
+ for (int i = 0; i < repeat; i++) {
+ mOutputConsole.write(command);
+ mOutputConsole.flush();
+ TimeUnit.MILLISECONDS.sleep(300);
+ }
+ }
+
+ mOutputConsole.write(command);
+ mOutputConsole.newLine();
+ /* Sleep less than 200ms between press and release */
+ TimeUnit.MILLISECONDS.sleep(100);
+ mOutputConsole.write("tx " + CecDevice.TV + CecDevice.PLAYBACK_1 + ":" +
+ CecMessage.USER_CONTROL_RELEASED);
+ mOutputConsole.flush();
+ }
+
/** Sends a message to the output console of the cec-client */
public void sendConsoleMessage(String message) throws Exception {
checkCecClient();
@@ -249,6 +281,47 @@
throw new Exception("Could not find message " + expectedMessage.name());
}
+ /**
+ * Looks for the CEC message incorrectMessage sent to CEC device toDevice on the cec-client
+ * communication channel and throws an exception if it finds the line that contains the message
+ * within the default timeout. If the CEC message is not found within the timeout, function
+ * returns without error.
+ */
+ public void checkOutputDoesNotContainMessage(CecDevice toDevice,
+ CecMessage incorrectMessage) throws Exception {
+ checkOutputDoesNotContainMessage(toDevice, incorrectMessage, DEFAULT_TIMEOUT);
+ }
+
+ /**
+ * Looks for the CEC message incorrectMessage sent to CEC device toDevice on the cec-client
+ * communication channel and throws an exception if it finds the line that contains the message
+ * within timeoutMillis. If the CEC message is not found within the timeout, function returns
+ * without error.
+ */
+ public void checkOutputDoesNotContainMessage(CecDevice toDevice, CecMessage incorrectMessage,
+ long timeoutMillis) throws Exception {
+
+ checkCecClient();
+ long startTime = System.currentTimeMillis();
+ long endTime = startTime;
+ Pattern pattern = Pattern.compile("(.*>>)(.*?)" +
+ "(" + targetDevice + toDevice + "):" +
+ "(" + incorrectMessage + ")(.*)",
+ Pattern.CASE_INSENSITIVE);
+
+ while ((endTime - startTime <= timeoutMillis)) {
+ if (mInputConsole.ready()) {
+ String line = mInputConsole.readLine();
+ if (pattern.matcher(line).matches()) {
+ CLog.v("Found " + incorrectMessage.name() + " in " + line);
+ throw new Exception("Found " + incorrectMessage.name() + " to " + toDevice +
+ " with params " + getParamsFromMessage(line));
+ }
+ }
+ endTime = System.currentTimeMillis();
+ }
+ }
+
/** Gets the hexadecimal ASCII character values of a string. */
public String getHexAsciiString(String string) {
String asciiString = "";
@@ -299,6 +372,17 @@
return Integer.parseInt(message, HEXADECIMAL_RADIX);
}
+ public String getAsciiStringFromMessage(String message) {
+ String params = getNibbles(message).substring(4);
+ StringBuilder builder = new StringBuilder();
+
+ for (int i = 2; i <= params.length(); i += 2) {
+ builder.append((char) hexStringToInt(params.substring(i - 2, i)));
+ }
+
+ return builder.toString();
+ }
+
/**
* Gets the params from a CEC message.
*/
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
index b751cf4..a1996a3 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
@@ -27,4 +27,16 @@
static final int PLAYBACK_DEVICE_TYPE = 0x04;
+ static final int CEC_CONTROL_SELECT = 0x0;
+ static final int CEC_CONTROL_UP = 0x1;
+ static final int CEC_CONTROL_DOWN = 0x2;
+ static final int CEC_CONTROL_LEFT = 0x3;
+ static final int CEC_CONTROL_RIGHT = 0x4;
+ static final int CEC_CONTROL_BACK = 0xd;
+ static final int CEC_CONTROL_VOLUME_UP = 0x41;
+ static final int CEC_CONTROL_VOLUME_DOWN = 0x42;
+ static final int CEC_CONTROL_MUTE = 0x43;
+
+ static final int UNRECOGNIZED_OPCODE = 0x0;
+
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecDeviceOsdNameTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecDeviceOsdNameTest.java
new file mode 100644
index 0000000..46306f1
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecDeviceOsdNameTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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.hdmicec.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+/** HDMI CEC tests related to the device reporting the device OSD name (Section 11.2.11) */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecDeviceOsdNameTest extends BaseHostJUnit4Test {
+ private static final CecDevice PLAYBACK_DEVICE = CecDevice.PLAYBACK_1;
+
+ @Rule
+ public HdmiCecClientWrapper hdmiCecClient =
+ new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+
+ /**
+ * Test 11.2.11-1a
+ * Tests that the device responds to a <GIVE_OSD_NAME> with a <SET_OSD_NAME> that has the
+ * correct device name in the parameters.
+ */
+ @Test
+ public void cect_11_2_11_1a_GiveOsdNameTest() throws Exception {
+ /* The params for <SET_OSD_NAME> only allow for 14 characters */
+ final int nameLength = 14;
+ ITestDevice device = getDevice();
+ String deviceName = device.executeShellCommand("settings get global device_name").trim();
+ if (deviceName.length() > nameLength) {
+ deviceName = deviceName.substring(0, nameLength).trim();
+ }
+ hdmiCecClient.sendCecMessage(CecDevice.TV, CecMessage.GIVE_OSD_NAME);
+ String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV, CecMessage.SET_OSD_NAME);
+ assertEquals(deviceName, hdmiCecClient.getAsciiStringFromMessage(message));
+ }
+
+ /**
+ * Test 11.2.11-1b
+ * Test updates the device_name in global properties and checks that the device responds to a
+ * <GIVE_OSD_NAME> with a <SET_OSD_NAME> that has the updated device name in the parameters.
+ */
+ @Test
+ public void cect_11_2_11_1b_UpdateAndGiveOsdNameTest() throws Exception {
+ final String testName = "test_name";
+ ITestDevice device = getDevice();
+ String originalName = device.executeShellCommand("settings get global device_name").trim();
+ try {
+ device.executeShellCommand("settings put global device_name '" + testName + "'");
+ hdmiCecClient.sendCecMessage(CecDevice.TV, CecMessage.GIVE_OSD_NAME);
+ String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV,
+ CecMessage.SET_OSD_NAME);
+ assertEquals(testName, hdmiCecClient.getAsciiStringFromMessage(message));
+ } finally {
+ device.executeShellCommand("settings put global device_name '" + originalName + "'");
+ }
+ }
+
+ /**
+ * Test 11.2.11-2
+ * Tests that the device does not respond to a <GIVE_OSD_NAME> from an unregistered device.
+ */
+ @Test
+ public void cect_11_2_11_2_UnregisteredDeviceGiveOsdNameTest() throws Exception {
+ hdmiCecClient.sendCecMessage(CecDevice.PLAYBACK_1, CecMessage.GIVE_OSD_NAME);
+ hdmiCecClient.checkOutputDoesNotContainMessage(CecDevice.PLAYBACK_1,
+ CecMessage.SET_OSD_NAME);
+ hdmiCecClient.sendCecMessage(CecDevice.BROADCAST, CecMessage.GIVE_OSD_NAME);
+ hdmiCecClient.checkOutputDoesNotContainMessage(CecDevice.BROADCAST,
+ CecMessage.SET_OSD_NAME);
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecPowerStatusTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecPowerStatusTest.java
index 30f8d5e..136c8da 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecPowerStatusTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecPowerStatusTest.java
@@ -26,6 +26,8 @@
import org.junit.runner.RunWith;
import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+
/** HDMI CEC test to check if the device reports power status correctly (Section 11.2.14) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecPowerStatusTest extends BaseHostJUnit4Test {
@@ -33,6 +35,8 @@
private static final int ON = 0x0;
private static final int OFF = 0x1;
+ private static final int WAIT_TIME = 5;
+
@Rule
public HdmiCecClientWrapper hdmiCecClient =
new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
@@ -65,6 +69,7 @@
/* Make sure the device is not booting up/in standby */
device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
device.executeShellCommand("input keyevent KEYCODE_SLEEP");
+ TimeUnit.SECONDS.sleep(WAIT_TIME);
hdmiCecClient.sendCecMessage(CecDevice.TV, CecMessage.GIVE_POWER_STATUS);
String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV,
CecMessage.REPORT_POWER_STATUS);
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecRemoteControlPassThroughTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecRemoteControlPassThroughTest.java
new file mode 100644
index 0000000..aa47adf
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecRemoteControlPassThroughTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 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.hdmicec.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
+
+/** HDMI CEC test to check if the device reports power status correctly (Section 11.2.13) */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Test {
+
+ /**
+ * The package name of the APK.
+ */
+ private static final String PACKAGE = "android.hdmicec.app";
+ /**
+ * The class name of the main activity in the APK.
+ */
+ private static final String CLASS = "HdmiCecKeyEventCapture";
+ /**
+ * The command to launch the main activity.
+ */
+ private static final String START_COMMAND = String.format(
+ "am start -W -a android.intent.action.MAIN -n %s/%s.%s", PACKAGE, PACKAGE, CLASS);
+ /**
+ * The command to clear the main activity.
+ */
+ private static final String CLEAR_COMMAND = String.format("pm clear %s", PACKAGE);
+
+ private static final int WAIT_TIME = 10;
+
+ @Rule
+ public HdmiCecClientWrapper hdmiCecClient =
+ new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+
+ private void lookForLog(String expectedOut) throws Exception {
+ ITestDevice device = getDevice();
+ TimeUnit.SECONDS.sleep(WAIT_TIME);
+ String logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
+ // Search for string.
+ String testString = "";
+ Scanner in = new Scanner(logs);
+ while (in.hasNextLine()) {
+ String line = in.nextLine();
+ if(line.startsWith("I/" + CLASS)) {
+ testString = line.split(":")[1].trim();
+ break;
+ }
+ }
+ device.executeAdbCommand("logcat", "-c");
+ assertEquals(expectedOut, testString);
+ }
+
+ /**
+ * Test 11.2.13-1
+ * Tests that the device responds correctly to a <USER_CONTROL_PRESSED> message followed
+ * immediately by a <USER_CONTROL_RELEASED> message.
+ */
+ @Test
+ public void cect_11_2_13_1_UserControlPressAndRelease() throws Exception {
+ ITestDevice device = getDevice();
+ // Clear activity
+ device.executeShellCommand(CLEAR_COMMAND);
+ // Clear logcat.
+ device.executeAdbCommand("logcat", "-c");
+ // Start the APK and wait for it to complete.
+ device.executeShellCommand(START_COMMAND);
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_UP, false);
+ lookForLog("Short press KEYCODE_DPAD_UP");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_DOWN, false);
+ lookForLog("Short press KEYCODE_DPAD_DOWN");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_LEFT, false);
+ lookForLog("Short press KEYCODE_DPAD_LEFT");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_RIGHT, false);
+ lookForLog("Short press KEYCODE_DPAD_RIGHT");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_SELECT, false);
+ lookForLog("Short press KEYCODE_DPAD_CENTER");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_BACK, false);
+ lookForLog("Short press KEYCODE_BACK");
+ }
+
+ /**
+ * Test 11.2.13-2
+ * Tests that the device responds correctly to a <USER_CONTROL_PRESSED> message for press and
+ * hold operations.
+ */
+ @Test
+ public void cect_11_2_13_2_UserControlPressAndHold() throws Exception {
+ ITestDevice device = getDevice();
+ // Clear activity
+ device.executeShellCommand(CLEAR_COMMAND);
+ // Clear logcat.
+ device.executeAdbCommand("logcat", "-c");
+ // Start the APK and wait for it to complete.
+ device.executeShellCommand(START_COMMAND);
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_UP, true);
+ lookForLog("Long press KEYCODE_DPAD_UP");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_DOWN, true);
+ lookForLog("Long press KEYCODE_DPAD_DOWN");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_LEFT, true);
+ lookForLog("Long press KEYCODE_DPAD_LEFT");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_RIGHT, true);
+ lookForLog("Long press KEYCODE_DPAD_RIGHT");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_SELECT, true);
+ lookForLog("Long press KEYCODE_DPAD_CENTER");
+ hdmiCecClient.sendUserControlPressAndRelease(HdmiCecConstants.CEC_CONTROL_BACK, true);
+ lookForLog("Long press KEYCODE_BACK");
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecRoutingControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecRoutingControlTest.java
index d95bbcd..cb6b536 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecRoutingControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecRoutingControlTest.java
@@ -26,6 +26,8 @@
import org.junit.runner.RunWith;
import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+
/** HDMI CEC test to test routing control (Section 11.2.2) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecRoutingControlTest extends BaseHostJUnit4Test {
@@ -33,7 +35,28 @@
private static final int PHYSICAL_ADDRESS = 0x1000;
@Rule
- public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public HdmiCecClientWrapper hdmiCecClient =
+ new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+
+ /**
+ * Test 11.2.2-1
+ * Tests that the device broadcasts a <ACTIVE_SOURCE> in response to a <SET_STREAM_PATH>, when
+ * the TV has switched to a different input.
+ */
+ @Test
+ public void cect_11_2_2_1_SetStreamPathToDut() throws Exception {
+ final long hdmi2Address = 0x2000;
+ /* Switch to HDMI2. Setup assumes DUT is connected to HDMI1. */
+ hdmiCecClient.sendCecMessage(CecDevice.PLAYBACK_2, CecDevice.BROADCAST,
+ CecMessage.ACTIVE_SOURCE, hdmiCecClient.formatParams(hdmi2Address));
+ TimeUnit.SECONDS.sleep(3);
+ hdmiCecClient.sendCecMessage(CecDevice.TV, CecDevice.BROADCAST,
+ CecMessage.SET_STREAM_PATH,
+ hdmiCecClient.formatParams(HdmiCecConstants.PHYSICAL_ADDRESS));
+ String message = hdmiCecClient.checkExpectedOutput(CecMessage.ACTIVE_SOURCE);
+ assertEquals(HdmiCecConstants.PHYSICAL_ADDRESS,
+ hdmiCecClient.getParamsFromMessage(message));
+ }
/**
* Test 11.2.2-2
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecSystemAudioControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecSystemAudioControlTest.java
new file mode 100644
index 0000000..c2b4678
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecSystemAudioControlTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 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.hdmicec.cts;
+
+import static org.junit.Assert.assertEquals;
+
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+/** HDMI CEC test to verify system audio control commands (Section 11.2.15) */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecSystemAudioControlTest extends BaseHostJUnit4Test {
+ private static final CecDevice PLAYBACK_DEVICE = CecDevice.PLAYBACK_1;
+
+ @Rule
+ public HdmiCecClientWrapper hdmiCecClient =
+ new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this, "-t", "a");
+
+ /**
+ * Test 11.2.15-10
+ * Tests that the device sends a <GIVE_SYSTEM_AUDIO_STATUS> message when brought out of standby
+ */
+ @Test
+ public void cect_11_2_15_10_GiveSystemAudioModeStatus() throws Exception {
+ ITestDevice device = getDevice();
+ device.executeShellCommand("input keyevent KEYCODE_SLEEP");
+ device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM,
+ CecMessage.GIVE_SYSTEM_AUDIO_MODE_STATUS);
+ }
+
+ /**
+ * Test 11.2.15-11
+ * Tests that the device sends <USER_CONTROL_PRESSED> and <USER_CONTROL_RELEASED> messages when
+ * the volume up and down keys are pressed on the DUT. Test also verifies that the
+ * <USER_CONTROL_PRESSED> message has the right control param.
+ */
+ @Test
+ public void cect_11_2_15_11_VolumeUpDownUserControlPressed() throws Exception {
+ ITestDevice device = getDevice();
+ device.executeShellCommand("input keyevent KEYCODE_VOLUME_UP");
+ String message = hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM,
+ CecMessage.USER_CONTROL_PRESSED);
+ assertEquals(HdmiCecConstants.CEC_CONTROL_VOLUME_UP,
+ hdmiCecClient.getParamsFromMessage(message));
+ hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM, CecMessage.USER_CONTROL_RELEASED);
+
+
+ device.executeShellCommand("input keyevent KEYCODE_VOLUME_DOWN");
+ message = hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM,
+ CecMessage.USER_CONTROL_PRESSED);
+ assertEquals(HdmiCecConstants.CEC_CONTROL_VOLUME_DOWN,
+ hdmiCecClient.getParamsFromMessage(message));
+ hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM, CecMessage.USER_CONTROL_RELEASED);
+ }
+
+ /**
+ * Test 11.2.15-12
+ * Tests that the device sends <USER_CONTROL_PRESSED> and <USER_CONTROL_RELEASED> messages when
+ * the mute key is pressed on the DUT. Test also verifies that the <USER_CONTROL_PRESSED>
+ * message has the right control param.
+ */
+ @Test
+ public void cect_11_2_15_12_MuteUserControlPressed() throws Exception {
+ ITestDevice device = getDevice();
+ device.executeShellCommand("input keyevent KEYCODE_MUTE");
+ String message = hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM,
+ CecMessage.USER_CONTROL_PRESSED);
+ assertEquals(HdmiCecConstants.CEC_CONTROL_MUTE,
+ hdmiCecClient.getParamsFromMessage(message));
+ hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM, CecMessage.USER_CONTROL_RELEASED);
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecVendorCommandsTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecVendorCommandsTest.java
new file mode 100644
index 0000000..49c5b3b
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecVendorCommandsTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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.hdmicec.cts;
+
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+/** HDMI CEC test to verify device vendor specific commands (Section 11.2.9) */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecVendorCommandsTest extends BaseHostJUnit4Test {
+ private static final CecDevice PLAYBACK_DEVICE = CecDevice.PLAYBACK_1;
+ private static final int INCORRECT_VENDOR_ID = 0x0;
+
+ @Rule
+ public HdmiCecClientWrapper hdmiCecClient =
+ new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+
+ /**
+ * Test 11.2.9-1
+ * Tests that the device responds to a <GIVE_DEVICE_VENDOR_ID> from various source devices
+ * with a <DEVICE_VENDOR_ID>.
+ */
+ @Test
+ public void cect_11_2_9_1_GiveDeviceVendorId() throws Exception {
+ for (CecDevice cecDevice : CecDevice.values()) {
+ hdmiCecClient.sendCecMessage(cecDevice, CecMessage.GIVE_DEVICE_VENDOR_ID);
+ String message = hdmiCecClient.checkExpectedOutput(CecMessage.DEVICE_VENDOR_ID);
+ assertNotEquals(INCORRECT_VENDOR_ID, hdmiCecClient.getParamsFromMessage(message));
+ }
+ }
+
+ /**
+ * Test 11.2.9-2
+ * Tests that the device broadcasts a <DEVICE_VENDOR_ID> message after successfull
+ * initialisation and address allocation.
+ */
+ @Test
+ public void cect_11_2_9_2_DeviceVendorIdOnInit() throws Exception {
+ ITestDevice device = getDevice();
+ device.executeShellCommand("reboot");
+ device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
+ String message = hdmiCecClient.checkExpectedOutput(CecMessage.DEVICE_VENDOR_ID);
+ assertNotEquals(INCORRECT_VENDOR_ID, hdmiCecClient.getParamsFromMessage(message));
+ }
+}
diff --git a/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
index 257d789..b2f5895 100644
--- a/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
@@ -448,7 +448,7 @@
return;
}
- if (getDevice().hasFeature("android.hardware.type.automotive")) {
+ if (getDevice().hasFeature("feature:android.hardware.type.automotive")) {
return;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp
new file mode 100644
index 0000000..85b8422
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp
@@ -0,0 +1,144 @@
+/**
+ * Copyright (C) 2019 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 "omxUtils.h"
+
+sp<IMediaPlayerService> mediaPlayerService = NULL;
+sp<IOMXNode> mOMXNode = 0;
+sp<IOMX> mOMX;
+omx_message msg;
+Mutex mLock;
+Condition mMessageAddedCondition;
+int32_t mLastMsgGeneration;
+int32_t mCurGeneration;
+List<omx_message> mMessageQueue;
+
+struct CodecObserver : public BnOMXObserver {
+ public:
+ CodecObserver(int32_t gen)
+ : mGeneration(gen) {
+ }
+
+ void onMessages(const std::list<omx_message> &messages) override;
+ int32_t mGeneration;
+
+ protected:
+ virtual ~CodecObserver() {
+ }
+};
+void handleMessages(int32_t gen, const std::list<omx_message> &messages) {
+ Mutex::Autolock autoLock(mLock);
+ for (std::list<omx_message>::const_iterator it = messages.cbegin();
+ it != messages.cend();) {
+ mMessageQueue.push_back(*it++);
+ mLastMsgGeneration = gen;
+ }
+ mMessageAddedCondition.signal();
+}
+void CodecObserver::onMessages(const std::list<omx_message> &messages) {
+ handleMessages(mGeneration, messages);
+}
+
+status_t dequeueMessageForNode(omx_message *msg, int64_t timeoutUs) {
+ int64_t finishBy = ALooper::GetNowUs() + timeoutUs;
+ status_t err = OK;
+
+ while (err != TIMED_OUT) {
+ Mutex::Autolock autoLock(mLock);
+ if (mLastMsgGeneration < mCurGeneration) {
+ mMessageQueue.clear();
+ }
+ // Messages are queued in batches, if the last batch queued is
+ // from a node that already expired, discard those messages.
+ List<omx_message>::iterator it = mMessageQueue.begin();
+ while (it != mMessageQueue.end()) {
+ *msg = *it;
+ mMessageQueue.erase(it);
+ return OK;
+ }
+ if (timeoutUs < 0) {
+ err = mMessageAddedCondition.wait(mLock);
+ } else {
+ err = mMessageAddedCondition.waitRelative(
+ mLock, (finishBy - ALooper::GetNowUs()) * 1000);
+ }
+ }
+ return err;
+}
+void omxUtilsCheckCmdExecution(char *name) {
+ status_t err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
+ if (err == TIMED_OUT) {
+ ALOGE("[omxUtils] OMX command timed out for %s, exiting the app", name);
+ exit (EXIT_FAILURE);
+ }
+}
+void omxExitOnError(status_t ret) {
+ if (ret != OK) {
+ exit (EXIT_FAILURE);
+ }
+}
+status_t omxUtilsInit(char *codecName) {
+ android::ProcessState::self()->startThreadPool();
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmx> tOmx = IOmx::getService();
+ if (tOmx == nullptr) {
+ return NO_INIT;
+ }
+ mOMX = new utils::LWOmx(tOmx);
+ sp<CodecObserver> observer = new CodecObserver(++mCurGeneration);
+ return mOMX->allocateNode(codecName, observer, &mOMXNode);
+}
+status_t omxUtilsGetParameter(int portIndex,
+ OMX_PARAM_PORTDEFINITIONTYPE *params) {
+ InitOMXParams(params);
+ params->nPortIndex = portIndex;
+ return mOMXNode->getParameter(OMX_IndexParamPortDefinition, params,
+ sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+}
+status_t omxUtilsSetParameter(int portIndex,
+ OMX_PARAM_PORTDEFINITIONTYPE *params) {
+ InitOMXParams(params);
+ params->nPortIndex = portIndex;
+ return mOMXNode->setParameter(OMX_IndexParamPortDefinition, params,
+ sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+}
+status_t omxUtilsSetPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
+ return mOMXNode->setPortMode(portIndex, mode);
+}
+status_t omxUtilsUseBuffer(OMX_U32 portIndex, const OMXBuffer &omxBuf,
+ android::BnOMX::buffer_id *buffer) {
+ return mOMXNode->useBuffer(portIndex, omxBuf, buffer);
+}
+status_t omxUtilsSendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) {
+ int ret = mOMXNode->sendCommand(cmd, param);
+ omxUtilsCheckCmdExecution((char *) __FUNCTION__);
+ return ret;
+}
+status_t omxUtilsEmptyBuffer(android::BnOMX::buffer_id buffer,
+ const OMXBuffer &omxBuf, OMX_U32 flags,
+ OMX_TICKS timestamp, int fenceFd) {
+ return mOMXNode->emptyBuffer(buffer, omxBuf, flags, timestamp, fenceFd);
+}
+status_t omxUtilsFillBuffer(android::BnOMX::buffer_id buffer,
+ const OMXBuffer &omxBuf, int fenceFd) {
+ return mOMXNode->fillBuffer(buffer, omxBuf, fenceFd);
+}
+status_t omxUtilsFreeBuffer(OMX_U32 portIndex,
+ android::BnOMX::buffer_id buffer) {
+ return mOMXNode->freeBuffer(portIndex, buffer);
+}
+status_t omxUtilsFreeNode() {
+ return mOMXNode->freeNode();
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h
new file mode 100644
index 0000000..16d7978
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h
@@ -0,0 +1,87 @@
+/**
+ * Copyright (C) 2019 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 <jni.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <binder/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
+#include <media/IOMX.h>
+#include <media/OMXBuffer.h>
+#include <ui/GraphicBuffer.h>
+#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
+#include <android/hardware/media/omx/1.0/IOmxObserver.h>
+#include <android/hardware/media/omx/1.0/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMapper.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/IGraphicBufferSource.h>
+#include <android/IOMXBufferSource.h>
+#include <media/omx/1.0/WOmx.h>
+#include <binder/MemoryDealer.h>
+#include "HardwareAPI.h"
+#include "OMX_Component.h"
+#include <binder/ProcessState.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+#include <inttypes.h>
+#include <utils/Log.h>
+
+#define DEFAULT_TIMEOUT 5000000
+#define OMX_UTILS_IP_PORT 0
+#define OMX_UTILS_OP_PORT 1
+
+using namespace android;
+typedef hidl::allocator::V1_0::IAllocator IAllocator;
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+struct Buffer {
+ IOMX::buffer_id mID;
+ sp<IMemory> mMemory;
+ hidl_memory mHidlMemory;
+ uint32_t mFlags;
+};
+
+status_t omxUtilsInit(char *codecName);
+status_t omxUtilsGetParameter(int portIndex,
+ OMX_PARAM_PORTDEFINITIONTYPE *params);
+status_t omxUtilsSetParameter(int portIndex,
+ OMX_PARAM_PORTDEFINITIONTYPE *params);
+status_t omxUtilsSetPortMode(OMX_U32 port_index, IOMX::PortMode mode);
+status_t omxUtilsUseBuffer(OMX_U32 portIndex, const OMXBuffer &omxBuf,
+ android::BnOMX::buffer_id *buffer);
+status_t omxUtilsSendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param);
+status_t omxUtilsEmptyBuffer(android::BnOMX::buffer_id buffer,
+ const OMXBuffer &omxBuf, OMX_U32 flags,
+ OMX_TICKS timestamp, int fenceFd);
+status_t omxUtilsFillBuffer(android::BnOMX::buffer_id buffer,
+ const OMXBuffer &omxBuf, int fenceFd);
+status_t omxUtilsFreeBuffer(OMX_U32 portIndex,
+ android::BnOMX::buffer_id buffer);
+status_t omxUtilsFreeNode();
+status_t dequeueMessageForNode(omx_message *msg, int64_t timeoutUs);
+void omxExitOnError(status_t ret);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index dd2a5e9..93b5cd9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -38,7 +38,10 @@
import org.json.JSONException;
import org.json.JSONObject;
+import java.util.regex.Pattern;
+import java.lang.Thread;
import static org.junit.Assert.*;
+import junit.framework.Assert;
public class AdbUtils {
@@ -59,7 +62,7 @@
/**
* Pushes and runs a binary to the selected device
*
- * @param pocName a string path to poc from the /res folder
+ * @param pocName name of the poc binary
* @param device device to be ran on
* @return the console output from the binary
*/
@@ -71,15 +74,35 @@
/**
* Pushes and runs a binary to the selected device
*
- * @param pocName a string path to poc from the /res folder
+ * @param pocName name of the poc binary
* @param device device to be ran on
* @param timeout time to wait for output in seconds
* @return the console output from the binary
*/
public static String runPoc(String pocName, ITestDevice device, int timeout) throws Exception {
+ return runPoc(pocName, device, timeout, null);
+ }
+
+ /**
+ * Pushes and runs a binary to the selected device
+ *
+ * @param pocName name of the poc binary
+ * @param device device to be ran on
+ * @param timeout time to wait for output in seconds
+ * @param arguments the input arguments for the poc
+ * @return the console output from the binary
+ */
+ public static String runPoc(String pocName, ITestDevice device, int timeout, String arguments)
+ throws Exception {
device.executeShellCommand("chmod +x /data/local/tmp/" + pocName);
CollectingOutputReceiver receiver = new CollectingOutputReceiver();
- device.executeShellCommand("/data/local/tmp/" + pocName, receiver, timeout, TimeUnit.SECONDS, 0);
+ if (arguments != null) {
+ device.executeShellCommand("/data/local/tmp/" + pocName + " " + arguments, receiver,
+ timeout, TimeUnit.SECONDS, 0);
+ } else {
+ device.executeShellCommand("/data/local/tmp/" + pocName, receiver, timeout,
+ TimeUnit.SECONDS, 0);
+ }
String output = receiver.getOutput();
return output;
}
@@ -87,16 +110,35 @@
/**
* Pushes and runs a binary to the selected device and ignores any of its output.
*
- * @param pocName a string path to poc from the /res folder
+ * @param pocName name of the poc binary
* @param device device to be ran on
* @param timeout time to wait for output in seconds
*/
public static void runPocNoOutput(String pocName, ITestDevice device, int timeout)
throws Exception {
+ runPocNoOutput(pocName, device, timeout, null);
+ }
+
+ /**
+ * Pushes and runs a binary with arguments to the selected device and
+ * ignores any of its output.
+ *
+ * @param pocName name of the poc binary
+ * @param device device to be ran on
+ * @param timeout time to wait for output in seconds
+ * @param arguments input arguments for the poc
+ */
+ public static void runPocNoOutput(String pocName, ITestDevice device, int timeout,
+ String arguments) throws Exception {
device.executeShellCommand("chmod +x /data/local/tmp/" + pocName);
NullOutputReceiver receiver = new NullOutputReceiver();
- device.executeShellCommand("/data/local/tmp/" + pocName, receiver, timeout,
- TimeUnit.SECONDS, 0);
+ if (arguments != null) {
+ device.executeShellCommand("/data/local/tmp/" + pocName + " " + arguments, receiver,
+ timeout, TimeUnit.SECONDS, 0);
+ } else {
+ device.executeShellCommand("/data/local/tmp/" + pocName, receiver, timeout,
+ TimeUnit.SECONDS, 0);
+ }
}
/**
@@ -338,5 +380,55 @@
} catch (JSONException e) {}
}
fail(error.toString());
+ }
+
+ /**
+ * Executes a given poc within a given timeout. Returns error if the
+ * given poc doesnt complete its execution within timeout. It also deletes
+ * the list of files provided.
+ *
+ * @param runner the thread which will be run
+ * @param timeout the timeout within which the thread's execution should
+ * complete
+ * @param device device to be ran on
+ * @param inputFiles list of files to be deleted
+ */
+ public static void runWithTimeoutDeleteFiles(Runnable runner, int timeout, ITestDevice device,
+ String[] inputFiles) throws Exception {
+ Thread t = new Thread(runner);
+ t.start();
+ boolean test_failed = false;
+ try {
+ t.join(timeout);
+ } catch (InterruptedException e) {
+ test_failed = true;
+ } finally {
+ if (inputFiles != null) {
+ for (String tempFile : inputFiles) {
+ AdbUtils.runCommandLine("rm /data/local/tmp/" + tempFile, device);
+ }
+ }
+ if (test_failed == true) {
+ Assert.fail("PoC was interrupted");
+ }
+ }
+ if (t.isAlive()) {
+ Assert.fail("PoC not completed within timeout of " + timeout + " ms");
+ }
+ }
+
+ /**
+ * Raises assert exception upon crash/error occurence
+ *
+ * @param crashPatternList array of crash log patterns to be checked for
+ * @param logcat String to be parsed
+ */
+ public static void checkCrash(String crashPatternList[], String logcat)
+ throws Exception {
+ for (String crashPattern : crashPatternList) {
+ assertFalse("Crash log pattern found!",
+ Pattern.compile(crashPattern, Pattern.MULTILINE)
+ .matcher(logcat).find());
+ }
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
new file mode 100644
index 0000000..bbfd78e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 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 com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import android.platform.test.annotations.SecurityTest;
+import java.util.regex.Pattern;
+
+@SecurityTest
+public class TestMedia extends SecurityTestCase {
+
+ final static int TIMEOUT_SEC = 9 * 60;
+ final static String RESOURCE_ROOT = "/";
+ final static String TMP_FILE_PATH = "/data/local/tmp/";
+
+ /****************************************************************
+ * To prevent merge conflicts, add tests for N below this comment,
+ * before any existing test methods
+ ****************************************************************/
+
+
+ /****************************************************************
+ * To prevent merge conflicts, add tests for O below this comment,
+ * before any existing test methods
+ ****************************************************************/
+
+
+ /****************************************************************
+ * To prevent merge conflicts, add tests for P below this comment,
+ * before any existing test methods
+ ****************************************************************/
+
+
+ /**
+ * Checks for linker errors
+ *
+ * @param binaryName name of the binary
+ * @param logcat String to be parsed
+ */
+ public static boolean isLinkerErrorPresent(String binaryName, String logcat)
+ throws Exception {
+ return Pattern
+ .compile("CANNOT LINK EXECUTABLE \"" + TMP_FILE_PATH
+ + binaryName + "\"", Pattern.MULTILINE)
+ .matcher(logcat).find();
+ }
+
+ /**
+ * Checks for crash
+ *
+ * @param binaryName Name of the binary
+ * @param errPattern error patterns to be checked for
+ * @param logcat String to be parsed
+ */
+ public static void checkCrash(String binaryName, String errPattern[],
+ String logcat) throws Exception {
+ String genericCrashPattern[] = {
+ "name: " + binaryName + " >>> " + TMP_FILE_PATH + binaryName
+ + " <<<\n.*?SIGABRT",
+ "name: " + binaryName + " >>> " + TMP_FILE_PATH + binaryName
+ + " <<<\n.*?SIGSEGV"};
+ AdbUtils.checkCrash(genericCrashPattern, logcat);
+ if (errPattern != null) {
+ AdbUtils.checkCrash(errPattern, logcat);
+ }
+ }
+
+ /**
+ * Pushes input files, runs the PoC and checks for crash and hang
+ *
+ * @param binaryName name of the binary
+ * @param inputFiles files required as input
+ * @param arguments arguments for running the binary
+ * @param device device to be run on
+ * @param errPattern error patterns to be checked for
+ */
+ public static void runMediaTest(String binaryName,
+ String inputFiles[], String arguments, ITestDevice device,
+ String errPattern[]) throws Exception {
+ if (inputFiles != null) {
+ for (String tempFile : inputFiles) {
+ AdbUtils.pushResource(RESOURCE_ROOT + tempFile,
+ TMP_FILE_PATH + tempFile, device);
+ }
+ }
+ AdbUtils.runCommandLine("logcat -c", device);
+ AdbUtils.runWithTimeoutDeleteFiles(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ AdbUtils.runPocNoOutput(binaryName, device,
+ TIMEOUT_SEC + 30, arguments);
+ } catch (Exception e) {
+ CLog.w("Exception: " + e.getMessage());
+ }
+ }
+ }, TIMEOUT_SEC * 1000, device, inputFiles);
+ String logcatOut = AdbUtils.runCommandLine("logcat -d", device);
+ boolean linkerErrorFound = isLinkerErrorPresent(binaryName, logcatOut);
+ if (!linkerErrorFound) {
+ checkCrash(binaryName, errPattern, logcatOut);
+ }
+ }
+}
diff --git a/hostsidetests/signedconfig/hostside/AndroidTest.xml b/hostsidetests/signedconfig/hostside/AndroidTest.xml
index 61b88e3..0a67693 100644
--- a/hostsidetests/signedconfig/hostside/AndroidTest.xml
+++ b/hostsidetests/signedconfig/hostside/AndroidTest.xml
@@ -17,6 +17,7 @@
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
diff --git a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
index 0842894..84b8562 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
@@ -33,6 +33,7 @@
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.storage.StorageManager;
import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -232,52 +233,6 @@
}
@Test
- public void testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk() throws Exception {
- stageSingleApk(TestApp.A1).assertSuccessful();
- StageSessionResult failedSessionResult = stageSingleApk(TestApp.A1);
- assertThat(failedSessionResult.getErrorMessage()).contains(
- "has been staged already by session");
- }
-
- @Test
- public void testAllowNonOverlappingMultipleStagedInstall_MultiPackageSinglePackage_Apk()
- throws Exception {
- stageMultipleApks(TestApp.A1, TestApp.B1).assertSuccessful();
- stageSingleApk(TestApp.C1).assertSuccessful();
- }
-
- @Test
- public void testFailOverlappingMultipleStagedInstall_BothMultiPackage_Apk() throws Exception {
- stageMultipleApks(TestApp.A1, TestApp.B1).assertSuccessful();
- StageSessionResult failedSessionResult = stageMultipleApks(TestApp.A2, TestApp.C1);
- assertThat(failedSessionResult.getErrorMessage()).contains(
- "has been staged already by session");
- }
-
- @Test
- public void testMultipleStagedInstall_ApkOnly_Commit()
- throws Exception {
- int firstSessionId = stageSingleApk(TestApp.A1).assertSuccessful().getSessionId();
- waitForIsReadyBroadcast(firstSessionId);
- int secondSessionId = stageSingleApk(TestApp.B1).assertSuccessful().getSessionId();
- waitForIsReadyBroadcast(secondSessionId);
- assertThat(getInstalledVersion(TestApp.A)).isEqualTo(-1);
- assertThat(getInstalledVersion(TestApp.A)).isEqualTo(-1);
- storeSessionIds(Arrays.asList(firstSessionId, secondSessionId));
- }
-
- @Test
- public void testMultipleStagedInstall_ApkOnly_VerifyPostReboot()
- throws Exception {
- List<Integer> sessionIds = retrieveLastSessionIds();
- for (int sessionId: sessionIds) {
- assertSessionApplied(sessionId);
- }
- assertThat(getInstalledVersion(TestApp.A)).isEqualTo(1);
- assertThat(getInstalledVersion(TestApp.B)).isEqualTo(1);
- }
-
- @Test
public void testAbandonStagedApkBeforeReboot_CommitAndAbandon() throws Exception {
int sessionId = stageSingleApk(TestApp.A1).assertSuccessful().getSessionId();
assertThat(getInstalledVersion(TestApp.A)).isEqualTo(-1);
@@ -805,6 +760,65 @@
waitForIsReadyBroadcast(sessionId);
}
+ /**
+ * Tests for staging and installing multiple staged sessions.
+ */
+
+ // Should fail to stage multiple sessions when check-point is not available
+ @Test
+ public void testFailStagingMultipleSessionsIfNoCheckPoint() throws Exception {
+ stageSingleApk(TestApp.A1).assertSuccessful();
+ StageSessionResult failedSessionResult = stageSingleApk(TestApp.B1);
+ assertThat(failedSessionResult.getErrorMessage()).contains(
+ "Cannot stage multiple sessions without checkpoint support");
+ }
+
+ @Test
+ public void testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk() throws Exception {
+ stageSingleApk(TestApp.A1).assertSuccessful();
+ StageSessionResult failedSessionResult = stageSingleApk(TestApp.A1);
+ assertThat(failedSessionResult.getErrorMessage()).contains(
+ "has been staged already by session");
+ }
+
+ @Test
+ public void testAllowNonOverlappingMultipleStagedInstall_MultiPackageSinglePackage_Apk()
+ throws Exception {
+ stageMultipleApks(TestApp.A1, TestApp.B1).assertSuccessful();
+ stageSingleApk(TestApp.C1).assertSuccessful();
+ }
+
+ @Test
+ public void testFailOverlappingMultipleStagedInstall_BothMultiPackage_Apk() throws Exception {
+ stageMultipleApks(TestApp.A1, TestApp.B1).assertSuccessful();
+ StageSessionResult failedSessionResult = stageMultipleApks(TestApp.A2, TestApp.C1);
+ assertThat(failedSessionResult.getErrorMessage()).contains(
+ "has been staged already by session");
+ }
+
+ @Test
+ public void testMultipleStagedInstall_ApkOnly_Commit()
+ throws Exception {
+ int firstSessionId = stageSingleApk(TestApp.A1).assertSuccessful().getSessionId();
+ waitForIsReadyBroadcast(firstSessionId);
+ int secondSessionId = stageSingleApk(TestApp.B1).assertSuccessful().getSessionId();
+ waitForIsReadyBroadcast(secondSessionId);
+ assertThat(getInstalledVersion(TestApp.A)).isEqualTo(-1);
+ assertThat(getInstalledVersion(TestApp.A)).isEqualTo(-1);
+ storeSessionIds(Arrays.asList(firstSessionId, secondSessionId));
+ }
+
+ @Test
+ public void testMultipleStagedInstall_ApkOnly_VerifyPostReboot()
+ throws Exception {
+ List<Integer> sessionIds = retrieveLastSessionIds();
+ for (int sessionId: sessionIds) {
+ assertSessionApplied(sessionId);
+ }
+ assertThat(getInstalledVersion(TestApp.A)).isEqualTo(1);
+ assertThat(getInstalledVersion(TestApp.B)).isEqualTo(1);
+ }
+
@Test
public void testSamegradeSystemApex_Commit() throws Exception {
final PackageInfo shim = InstrumentationRegistry.getInstrumentation().getContext()
@@ -1086,4 +1100,11 @@
assertThat(info.getSessionId()).isEqualTo(sessionId);
return info;
}
+
+ @Test
+ public void isCheckpointSupported() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
+ assertThat(sm.isCheckpointSupported()).isTrue();
+ }
}
diff --git a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
index 377a0c1..ea4df01 100644
--- a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
@@ -94,33 +94,6 @@
}
@Test
- public void testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk() throws Exception {
- runPhase("testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk");
- }
-
- @Test
- public void testAllowNonOverlappingMultipleStagedInstall_MultiPackageSinglePackage_Apk()
- throws Exception {
- runPhase("testAllowNonOverlappingMultipleStagedInstall_MultiPackageSinglePackage_Apk");
- }
-
- @Test
- public void testFailOverlappingMultipleStagedInstall_BothMultiPackage_Apk() throws Exception {
- runPhase("testFailOverlappingMultipleStagedInstall_BothMultiPackage_Apk");
- }
-
- /**
- * Tests for installing multiple staged sessions at the same time
- */
- @Test
- @LargeTest
- public void testMultipleStagedInstall_ApkOnly() throws Exception {
- runPhase("testMultipleStagedInstall_ApkOnly_Commit");
- getDevice().reboot();
- runPhase("testMultipleStagedInstall_ApkOnly_VerifyPostReboot");
- }
-
- @Test
@LargeTest
public void testAbandonStagedApkBeforeReboot() throws Exception {
runPhase("testAbandonStagedApkBeforeReboot_CommitAndAbandon");
@@ -145,6 +118,7 @@
@Test
public void testGetActiveStagedSessions() throws Exception {
+ assumeTrue(isCheckpointSupported());
runPhase("testGetActiveStagedSessions");
}
@@ -155,6 +129,7 @@
@Test
public void testGetActiveStagedSessions_MultiApkSession() throws Exception {
+ assumeTrue(isCheckpointSupported());
runPhase("testGetActiveStagedSessions_MultiApkSession");
}
@@ -424,6 +399,44 @@
runPhase("testAfterRotationNewKeyCanUpdateFurtherWithoutLineage");
}
+ /**
+ * Tests for staging and installing multiple staged sessions.
+ */
+
+ // Should fail to stage multiple sessions when check-point is not available
+ @Test
+ public void testFailStagingMultipleSessionsIfNoCheckPoint() throws Exception {
+ assumeFalse(isCheckpointSupported());
+ runPhase("testFailStagingMultipleSessionsIfNoCheckPoint");
+ }
+
+ @Test
+ public void testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk() throws Exception {
+ runPhase("testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk");
+ }
+
+ @Test
+ public void testAllowNonOverlappingMultipleStagedInstall_MultiPackageSinglePackage_Apk()
+ throws Exception {
+ assumeTrue(isCheckpointSupported());
+ runPhase("testAllowNonOverlappingMultipleStagedInstall_MultiPackageSinglePackage_Apk");
+ }
+
+ @Test
+ public void testFailOverlappingMultipleStagedInstall_BothMultiPackage_Apk() throws Exception {
+ assumeTrue(isCheckpointSupported());
+ runPhase("testFailOverlappingMultipleStagedInstall_BothMultiPackage_Apk");
+ }
+
+ // Test for installing multiple staged sessions at the same time
+ @Test
+ @LargeTest
+ public void testMultipleStagedInstall_ApkOnly() throws Exception {
+ runPhase("testMultipleStagedInstall_ApkOnly_Commit");
+ getDevice().reboot();
+ runPhase("testMultipleStagedInstall_ApkOnly_VerifyPostReboot");
+ }
+
@Test
@LargeTest
public void testSamegradeSystemApex() throws Exception {
@@ -519,6 +532,14 @@
return "Failed to get staged sessions";
}
}
+ }
+ private boolean isCheckpointSupported() throws Exception {
+ try {
+ runPhase("isCheckpointSupported");
+ return true;
+ } catch (AssertionError ignore) {
+ return false;
+ }
}
}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
index fc1b57e..9c55177 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
@@ -42,6 +42,7 @@
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
+import android.location.GnssStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
@@ -270,6 +271,81 @@
}
@Test
+ public void testGpsStatus() {
+ Context context = InstrumentationRegistry.getContext();
+ final LocationManager locManager = context.getSystemService(LocationManager.class);
+
+ if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
+ Log.e(TAG, "GPS provider is not enabled");
+ return;
+ }
+
+ // Time out set to 85 seconds (5 seconds for sleep and a possible 85 seconds if TTFF takes
+ // max time which would be around 90 seconds.
+ // This is based on similar location cts test timeout values.
+ final int TIMEOUT_IN_MSEC = 85_000;
+ final int SLEEP_TIME_IN_MSEC = 5_000;
+ // TTFF could take up to 90 seconds, thus we need to wait till TTFF does occur if it does
+ // not occur in the first SLEEP_TIME_IN_MSEC
+ final CountDownLatch mLatchTtff = new CountDownLatch(1);
+
+ GnssStatus.Callback gnssStatusCallback = new GnssStatus.Callback() {
+ @Override
+ public void onStarted() {
+ Log.v(TAG, "Gnss Status Listener Started");
+ }
+
+ @Override
+ public void onStopped() {
+ Log.v(TAG, "Gnss Status Listener Stopped");
+ }
+
+ @Override
+ public void onFirstFix(int ttffMillis) {
+ Log.v(TAG, "Gnss Status Listener Received TTFF");
+ mLatchTtff.countDown();
+ }
+
+ @Override
+ public void onSatelliteStatusChanged(GnssStatus status) {
+ Log.v(TAG, "Gnss Status Listener Received Status Update");
+ }
+ };
+
+ boolean gnssStatusCallbackAdded = locManager.registerGnssStatusCallback(
+ gnssStatusCallback, new Handler(Looper.getMainLooper()));
+ if (!gnssStatusCallbackAdded) {
+ // Registration of GnssMeasurements listener has failed, this indicates a platform bug.
+ Log.e(TAG, "Failed to start gnss status callback");
+ }
+
+ final LocationListener locListener = new LocationListener() {
+ public void onLocationChanged(Location location) {
+ Log.v(TAG, "onLocationChanged: location has been obtained");
+ }
+ public void onProviderDisabled(String provider) {
+ Log.v(TAG, "onProviderDisabled " + provider);
+ }
+ public void onProviderEnabled(String provider) {
+ Log.v(TAG, "onProviderEnabled " + provider);
+ }
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ Log.v(TAG, "onStatusChanged " + provider + " " + status);
+ }
+ };
+
+ locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
+ 0,
+ 0 /* minDistance */,
+ locListener,
+ Looper.getMainLooper());
+ sleep(SLEEP_TIME_IN_MSEC);
+ waitForReceiver(context, TIMEOUT_IN_MSEC, mLatchTtff, null);
+ locManager.removeUpdates(locListener);
+ locManager.unregisterGnssStatusCallback(gnssStatusCallback);
+ }
+
+ @Test
public void testScreenBrightness() {
Context context = InstrumentationRegistry.getContext();
PowerManager pm = context.getSystemService(PowerManager.class);
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index a51af81..0de0d03 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -548,6 +548,86 @@
}
}
+ public void testGpsStatus() throws Exception {
+ if (statsdDisabled()) {
+ return;
+ }
+ if (!hasFeature(FEATURE_LOCATION_GPS, true)) return;
+ // Whitelist this app against background location request throttling
+ String origWhitelist = getDevice().executeShellCommand(
+ "settings get global location_background_throttle_package_whitelist").trim();
+ getDevice().executeShellCommand(String.format(
+ "settings put global location_background_throttle_package_whitelist %s",
+ DEVICE_SIDE_TEST_PACKAGE));
+
+ try {
+ final int atom = Atom.GPS_LOCATION_STATUS_REPORTED_FIELD_NUMBER;
+
+ createAndUploadConfig(atom);
+ Thread.sleep(WAIT_TIME_SHORT);
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testGpsStatus");
+
+ // Sorted list of events in order in which they occurred.
+ List<EventMetricData> data = getEventMetricDataList();
+
+ /*
+ We will sleep for a minimum of 5 seconds and if time to first fix is at max we would
+ wait for at most 90 seconds. Meaning we should see a minimum of 1 status message and a
+ maximum of 90 status messages.
+ */
+ assertThat(data.size()).isAtLeast(1);
+ assertThat(data.size()).isAtMost(90);
+ } finally {
+ if ("null".equals(origWhitelist) || "".equals(origWhitelist)) {
+ getDevice().executeShellCommand(
+ "settings delete global location_background_throttle_package_whitelist");
+ } else {
+ getDevice().executeShellCommand(String.format(
+ "settings put global location_background_throttle_package_whitelist %s",
+ origWhitelist));
+ }
+ }
+ }
+
+ public void testGpsTimeToFirstFix() throws Exception {
+ if (statsdDisabled()) {
+ return;
+ }
+ if (!hasFeature(FEATURE_LOCATION_GPS, true)) return;
+ // Whitelist this app against background location request throttling
+ String origWhitelist = getDevice().executeShellCommand(
+ "settings get global location_background_throttle_package_whitelist").trim();
+ getDevice().executeShellCommand(String.format(
+ "settings put global location_background_throttle_package_whitelist %s",
+ DEVICE_SIDE_TEST_PACKAGE));
+
+ try {
+ final int atom = Atom.GPS_TIME_TO_FIRST_FIX_REPORTED_FIELD_NUMBER;
+
+ createAndUploadConfig(atom);
+ Thread.sleep(WAIT_TIME_SHORT);
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testGpsStatus");
+
+ // Sorted list of events in order in which they occurred.
+ List<EventMetricData> data = getEventMetricDataList();
+
+ assertThat(data.size()).isEqualTo(1);
+ assertThat(data.get(0).getAtom().getGpsTimeToFirstFixReported()
+ .getTimeToFirstFixMillis()).isGreaterThan(0);
+ assertThat(data.get(0).getAtom().getGpsTimeToFirstFixReported()
+ .getTimeToFirstFixMillis()).isAtMost(90_000);
+ } finally {
+ if ("null".equals(origWhitelist) || "".equals(origWhitelist)) {
+ getDevice().executeShellCommand(
+ "settings delete global location_background_throttle_package_whitelist");
+ } else {
+ getDevice().executeShellCommand(String.format(
+ "settings put global location_background_throttle_package_whitelist %s",
+ origWhitelist));
+ }
+ }
+ }
+
public void testMediaCodecActivity() throws Exception {
if (statsdDisabled()) {
return;
diff --git a/tests/accessibility/res/xml/speaking_accessibilityservice.xml b/tests/accessibility/res/xml/speaking_accessibilityservice.xml
index 339245a..249c381 100644
--- a/tests/accessibility/res/xml/speaking_accessibilityservice.xml
+++ b/tests/accessibility/res/xml/speaking_accessibilityservice.xml
@@ -16,7 +16,7 @@
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackSpoken"
- android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagRequestTouchExplorationMode|flagReportViewIds|flagRequestFilterKeyEvents|flagRequestShortcutWarningDialogSpokenFeedback|flagHandleShortcut"
+ android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagRequestTouchExplorationMode|flagReportViewIds|flagRequestFilterKeyEvents|flagRequestShortcutWarningDialogSpokenFeedback"
android:canRetrieveWindowContent="true"
android:canRequestTouchExplorationMode="true"
android:canRequestFilterKeyEvents="true"
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
index b8bea69de..f4abdf1 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
@@ -87,8 +87,7 @@
| AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE
| AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS
| AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS
- | AccessibilityServiceInfo.FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK
- | AccessibilityServiceInfo.FLAG_HANDLE_SHORTCUT,
+ | AccessibilityServiceInfo.FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK,
speakingService.flags);
assertSame(0l, speakingService.notificationTimeout);
assertEquals("Some description", speakingService.getDescription());
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
index ee38997..01d1659 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
@@ -128,8 +128,7 @@
AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES));
assertEquals("FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK", AccessibilityServiceInfo.flagToString(
AccessibilityServiceInfo.FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK));
- assertEquals("FLAG_HANDLE_SHORTCUT", AccessibilityServiceInfo.flagToString(
- AccessibilityServiceInfo.FLAG_HANDLE_SHORTCUT));
+
}
/**
diff --git a/tests/app/app/src/android/app/stubs/CommandReceiver.java b/tests/app/app/src/android/app/stubs/CommandReceiver.java
index 674fd41..70b02aa 100644
--- a/tests/app/app/src/android/app/stubs/CommandReceiver.java
+++ b/tests/app/app/src/android/app/stubs/CommandReceiver.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -48,6 +47,9 @@
public static final String EXTRA_FLAGS = "android.app.stubs.extra.FLAGS";
public static final String SERVICE_NAME = "android.app.stubs.LocalService";
+ public static final String FG_SERVICE_NAME = "android.app.stubs.LocalForegroundService";
+ public static final String FG_LOCATION_SERVICE_NAME =
+ "android.app.stubs.LocalForegroundServiceLocation";
private static ArrayMap<String,ServiceConnection> sServiceMap = new ArrayMap<>();
@@ -71,20 +73,16 @@
doUnbindService(context, intent);
break;
case COMMAND_START_FOREGROUND_SERVICE:
- doStartForegroundService(context, LocalForegroundService.class);
+ doStartForegroundService(context, intent);
break;
case COMMAND_STOP_FOREGROUND_SERVICE:
- doStopForegroundService(context, LocalForegroundService.class);
+ doStopForegroundService(context, intent, FG_SERVICE_NAME);
break;
case COMMAND_START_FOREGROUND_SERVICE_LOCATION:
- int type = intent.getIntExtra(
- LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE,
- ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST);
- doStartForegroundServiceWithType(context, LocalForegroundServiceLocation.class,
- type);
+ doStartForegroundServiceWithType(context, intent);
break;
case COMMAND_STOP_FOREGROUND_SERVICE_LOCATION:
- doStopForegroundService(context, LocalForegroundServiceLocation.class);
+ doStopForegroundService(context, intent, FG_LOCATION_SERVICE_NAME);
break;
case COMMAND_START_ALERT_SERVICE:
doStartAlertService(context);
@@ -112,23 +110,29 @@
context.unbindService(sServiceMap.remove(targetPackage));
}
- private void doStartForegroundService(Context context, Class cls) {
- Intent fgsIntent = new Intent(context, cls);
+ private void doStartForegroundService(Context context, Intent commandIntent) {
+ String targetPackage = getTargetPackage(commandIntent);
+ Intent fgsIntent = new Intent();
+ fgsIntent.setComponent(new ComponentName(targetPackage, FG_SERVICE_NAME));
int command = LocalForegroundService.COMMAND_START_FOREGROUND;
fgsIntent.putExtras(LocalForegroundService.newCommand(new Binder(), command));
context.startForegroundService(fgsIntent);
}
- private void doStartForegroundServiceWithType(Context context, Class cls, int type) {
- Intent fgsIntent = new Intent(context, cls);
+ private void doStartForegroundServiceWithType(Context context, Intent commandIntent) {
+ String targetPackage = getTargetPackage(commandIntent);
+ Intent fgsIntent = new Intent();
+ fgsIntent.setComponent(new ComponentName(targetPackage, FG_LOCATION_SERVICE_NAME));
int command = LocalForegroundServiceLocation.COMMAND_START_FOREGROUND_WITH_TYPE;
fgsIntent.putExtras(LocalForegroundService.newCommand(new Binder(), command));
- fgsIntent.putExtra(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE, type);
context.startForegroundService(fgsIntent);
}
- private void doStopForegroundService(Context context, Class cls) {
- Intent fgsIntent = new Intent(context, cls);
+ private void doStopForegroundService(Context context, Intent commandIntent,
+ String serviceName) {
+ String targetPackage = getTargetPackage(commandIntent);
+ Intent fgsIntent = new Intent();
+ fgsIntent.setComponent(new ComponentName(targetPackage, serviceName));
context.stopService(fgsIntent);
}
diff --git a/tests/app/src/android/app/cts/ActivityManagerApi29Test.java b/tests/app/src/android/app/cts/ActivityManagerApi29Test.java
index 8553698..4c56d1c 100644
--- a/tests/app/src/android/app/cts/ActivityManagerApi29Test.java
+++ b/tests/app/src/android/app/cts/ActivityManagerApi29Test.java
@@ -67,7 +67,7 @@
private static final String SIMPLE_ACTIVITY = ".SimpleActivity";
private static final String SERVICE_NAME = ".LocationForegroundService";
private static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
- private static final int WAITFOR_MSEC = 5000;
+ private static final int WAITFOR_MSEC = 10000;
private static final int NOTEOP_COUNT = 5;
private static Instrumentation sInstrumentation = InstrumentationRegistry.getInstrumentation();
private static Context sContext = sInstrumentation.getContext();
@@ -90,6 +90,7 @@
@Before
public void setUp() throws Exception {
+ CtsAppTestUtils.turnScreenOn(sInstrumentation, sContext);
// PACKAGE_NAME's targetSdkVersion is 29, when ACCESS_COARSE_LOCATION is granted, appOp is
// MODE_FOREGROUND (In API level lower than 29, appOp is MODE_ALLOWED).
assertEquals(AppOpsManager.MODE_FOREGROUND,
diff --git a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
index 6a23c47..ca3bdf1 100644
--- a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
@@ -30,7 +30,6 @@
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.Instrumentation;
-import android.app.KeyguardManager;
import android.app.cts.android.app.cts.tools.ServiceConnectionHandler;
import android.app.cts.android.app.cts.tools.ServiceProcessController;
import android.app.cts.android.app.cts.tools.SyncOrderedBroadcast;
@@ -51,7 +50,6 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
-import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.server.wm.WindowManagerState;
@@ -62,7 +60,6 @@
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
-import com.android.compatibility.common.util.CommonTestUtils;
import com.android.compatibility.common.util.SystemUtil;
public class ActivityManagerProcessStateTest extends InstrumentationTestCase {
@@ -77,8 +74,8 @@
PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, PACKAGE_NAME_APP3
};
- private static final int WAIT_TIME = 2000;
- private static final int WAITFOR_MSEC = 5000;
+ private static final int WAIT_TIME = 10000;
+ private static final int WAITFOR_MSEC = 10000;
// A secondary test activity from another APK.
static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp";
static final String SIMPLE_SERVICE = ".SimpleService";
@@ -147,7 +144,7 @@
mContext.stopService(mServiceIntent);
mContext.stopService(mService2Intent);
mContext.stopService(mService3Intent);
- turnScreenOn();
+ CtsAppTestUtils.turnScreenOn(mInstrumentation, mContext);
removeTestAppFromWhitelists();
mAppCount = 0;
}
@@ -172,43 +169,11 @@
}
}
- private void turnScreenOn() throws Exception {
- executeShellCmd("input keyevent KEYCODE_WAKEUP");
- executeShellCmd("wm dismiss-keyguard");
- /*
- Wait until the screen becomes interactive to start the test cases.
- Otherwise the procstat may start in TOP_SLEEPING state, and this
- causes test case testBackgroundCheckActivityService to fail.
- Note: There could still a small chance the procstat is TOP_SLEEPING
- when the predicate returns true.
- */
- CommonTestUtils.waitUntil("Device does not wake up after 5 seconds", 5,
- () -> {
- return isScreenInteractive() && !isKeyguardLocked();
- });
- }
-
private void removeTestAppFromWhitelists() throws Exception {
- executeShellCmd("cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME);
- executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
- }
-
- private String executeShellCmd(String cmd) throws Exception {
- final String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
- Log.d(TAG, String.format("Output for '%s': %s", cmd, result));
- return result;
- }
-
- private boolean isScreenInteractive() {
- final PowerManager powerManager =
- (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- return powerManager.isInteractive();
- }
-
- private boolean isKeyguardLocked() {
- final KeyguardManager keyguardManager =
- (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- return keyguardManager.isKeyguardLocked();
+ CtsAppTestUtils.executeShellCmd(mInstrumentation,
+ "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME);
+ CtsAppTestUtils.executeShellCmd(mInstrumentation,
+ "cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
}
private void waitForAppFocus(String waitForApp, long waitTime) {
@@ -533,7 +498,8 @@
uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
- executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
+ CtsAppTestUtils.executeShellCmd(mInstrumentation,
+ "cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
// Going off the temp whitelist causes a spurious proc state report... that's
// not ideal, but okay.
@@ -934,7 +900,8 @@
}
conn.waitForConnect();
- final String expectedActivityState = (isScreenInteractive() && !isKeyguardLocked())
+ final String expectedActivityState = (CtsAppTestUtils.isScreenInteractive(mContext)
+ && !CtsAppTestUtils.isKeyguardLocked(mContext))
? WatchUidRunner.STATE_TOP : WatchUidRunner.STATE_TOP_SLEEPING;
// Also make sure the uid state reports are as expected.
uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
@@ -1081,7 +1048,8 @@
uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
// Remove tempwhitelist avoid temp white list block idle command and app crash occur.
- executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
+ CtsAppTestUtils.executeShellCmd(mInstrumentation,
+ "cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
// Good, now stop the service and wait for it to go away.
mContext.stopService(mServiceStartForegroundIntent);
conn.waitForDisconnect();
@@ -1566,13 +1534,13 @@
// Check that the app's proc state has fallen
uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
-
+ } finally {
// Clean up: unbind services to avoid from interferences with other tests
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
PACKAGE_NAME_APP1, PACKAGE_NAME_APP3, 0, null);
- } finally {
+
uid1Watcher.finish();
uid3Watcher.finish();
}
@@ -1647,7 +1615,7 @@
uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
-
+ } finally {
// Clean up: unbind services to avoid from interferences with other tests
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
@@ -1656,7 +1624,7 @@
// Stop the foreground service
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
- } finally {
+
uid1Watcher.finish();
uid2Watcher.finish();
uid3Watcher.finish();
@@ -1723,7 +1691,7 @@
uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
-
+ } finally {
// Clean up: unbind services to avoid from interferences with other tests
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
@@ -1735,7 +1703,7 @@
PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, 0, null);
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);
- } finally {
+
uid1Watcher.finish();
uid2Watcher.finish();
uid3Watcher.finish();
@@ -1868,13 +1836,13 @@
mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE,
WatchUidRunner.STATE_CACHED_EMPTY,
new Integer(PROCESS_CAPABILITY_NONE));
-
+ } finally {
// Clean up: unbind services to avoid from interferences with other tests
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
mAppInfo[0].packageName, mAppInfo[1].packageName, 0, null);
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
- mAppInfo[0].packageName, mAppInfo[2].packageName, 0, bundle);
- } finally {
+ mAppInfo[0].packageName, mAppInfo[2].packageName, 0, null);
+
shutdownWatchers();
}
}
@@ -1906,13 +1874,13 @@
STUB_PACKAGE_NAME, mAppInfo[1].packageName, 0, bundle);
mWatchers[1].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP,
new Integer(PROCESS_CAPABILITY_ALL));
-
+ } finally {
// Clean up: unbind services to avoid from interferences with other tests
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
STUB_PACKAGE_NAME, mAppInfo[0].packageName, 0, null);
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
- STUB_PACKAGE_NAME, mAppInfo[1].packageName, 0, bundle);
- } finally {
+ STUB_PACKAGE_NAME, mAppInfo[1].packageName, 0, null);
+
shutdownWatchers();
if (activity != null) {
activity.finish();
@@ -2033,7 +2001,7 @@
uid3Listener.waitForValue(
IMPORTANCE_CACHED,
IMPORTANCE_CACHED);
-
+ } finally {
// Clean up: unbind services to avoid from interferences with other tests
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
@@ -2041,7 +2009,7 @@
PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);
- } finally {
+
uid1Listener.unregister();
uid1ServiceListener.unregister();
uid2Listener.unregister();
diff --git a/tests/app/src/android/app/cts/CtsAppTestUtils.java b/tests/app/src/android/app/cts/CtsAppTestUtils.java
new file mode 100644
index 0000000..9f69385
--- /dev/null
+++ b/tests/app/src/android/app/cts/CtsAppTestUtils.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 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.app.cts;
+
+import android.app.Instrumentation;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.os.PowerManager;
+import android.util.Log;
+
+import com.android.compatibility.common.util.CommonTestUtils;
+import com.android.compatibility.common.util.SystemUtil;
+
+class CtsAppTestUtils {
+ private static final String TAG = CtsAppTestUtils.class.getName();
+
+ public static String executeShellCmd(Instrumentation instrumentation, String cmd)
+ throws Exception {
+ final String result = SystemUtil.runShellCommand(instrumentation, cmd);
+ Log.d(TAG, String.format("Output for '%s': %s", cmd, result));
+ return result;
+ }
+
+ public static boolean isScreenInteractive(Context context) {
+ final PowerManager powerManager =
+ (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ return powerManager.isInteractive();
+ }
+
+ public static boolean isKeyguardLocked(Context context) {
+ final KeyguardManager keyguardManager =
+ (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
+ return keyguardManager.isKeyguardLocked();
+ }
+
+ public static void turnScreenOn(Instrumentation instrumentation, Context context)
+ throws Exception {
+ executeShellCmd(instrumentation, "input keyevent KEYCODE_WAKEUP");
+ executeShellCmd(instrumentation, "wm dismiss-keyguard");
+ CommonTestUtils.waitUntil("Device does not wake up after 5 seconds", 5,
+ () -> {
+ return isScreenInteractive(context)
+ && !isKeyguardLocked(context);
+ });
+ }
+}
diff --git a/tests/app/src/android/app/cts/ServiceTest.java b/tests/app/src/android/app/cts/ServiceTest.java
index 5486082..792ef5d 100644
--- a/tests/app/src/android/app/cts/ServiceTest.java
+++ b/tests/app/src/android/app/cts/ServiceTest.java
@@ -46,6 +46,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
@@ -1452,6 +1453,22 @@
return mInfo != null ? mInfo.getConnection().getUid() : mUid;
}
+ int getUserId() {
+ return UserHandle.getUserHandleForUid(getUid()).getIdentifier();
+ }
+
+ int getAppId() {
+ return UserHandle.getAppId(getUid());
+ }
+
+ boolean isEquivalentTo(ProcessRecordProto proc) {
+ int procAppId = proc.isolatedAppId != 0 ? proc.isolatedAppId : UserHandle.getAppId(
+ proc.uid);
+
+ // Compare appid and userid separately because UserHandle.getUid is @hide.
+ return procAppId == getAppId() && proc.userId == getUserId();
+ }
+
int getFlags() {
return mFlags;
}
@@ -1541,20 +1558,18 @@
logProc(i, proc);
final LruOrderItem lru = orderItems[orderI];
Log.i("XXXXXXXX", "Expecting uid: " + lru.getUid());
- int procUid = proc.isolatedAppId != 0 ? proc.isolatedAppId : proc.uid;
- if (procUid != lru.getUid()) {
+ if (!lru.isEquivalentTo(proc)) {
if ((lru.getFlags() & LruOrderItem.FLAG_SKIP_UNKNOWN) != 0) {
while (i > 0) {
i--;
proc = procs.get(i);
logProc(i, proc);
- procUid = proc.isolatedAppId != 0 ? proc.isolatedAppId : proc.uid;
- if (procUid == lru.getUid()) {
+ if (lru.isEquivalentTo(proc)) {
break;
}
}
}
- if (procUid != lru.getUid()) {
+ if (!lru.isEquivalentTo(proc)) {
if ((lru.getFlags() & LruOrderItem.FLAG_SKIP_UNKNOWN) != 0) {
fail("Didn't find expected LRU proc uid=" + lru.getUid());
}
diff --git a/tests/appsearch/Android.bp b/tests/appsearch/Android.bp
new file mode 100644
index 0000000..ed6710d
--- /dev/null
+++ b/tests/appsearch/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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.
+
+android_test {
+ name: "CtsAppSearchTestCases",
+ defaults: ["cts_defaults"],
+ static_libs: [
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "compatibility-device-util-axt",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ platform_apis: true,
+}
\ No newline at end of file
diff --git a/tests/appsearch/AndroidManifest.xml b/tests/appsearch/AndroidManifest.xml
new file mode 100644
index 0000000..7eac46b
--- /dev/null
+++ b/tests/appsearch/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.appsearch" >
+ <application android:label="CtsAppSearchTestCases">
+ <uses-library android:name="android.test.runner"/>
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.appsearch"
+ android:label="CtsAppSearchTestCases"/>
+</manifest>
diff --git a/tests/appsearch/AndroidTest.xml b/tests/appsearch/AndroidTest.xml
new file mode 100644
index 0000000..ddf7c1f
--- /dev/null
+++ b/tests/appsearch/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<configuration description="Config for CTS AppSearch test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAppSearchTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.cts.appsearch" />
+ </test>
+</configuration>
diff --git a/tests/appsearch/src/com/android/cts/appsearch/AppSearchManagerTest.java b/tests/appsearch/src/com/android/cts/appsearch/AppSearchManagerTest.java
new file mode 100644
index 0000000..e43bb5d
--- /dev/null
+++ b/tests/appsearch/src/com/android/cts/appsearch/AppSearchManagerTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.appsearch;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+@RunWith(AndroidJUnit4.class)
+public class AppSearchManagerTest {
+ @Test
+ public void testGetService() {
+ assertNotNull(InstrumentationRegistry.getInstrumentation().getContext()
+ .getSystemService(Context.APP_SEARCH_SERVICE));
+ }
+}
diff --git a/tests/autofillservice/res/layout/list_item_cancel.xml b/tests/autofillservice/res/layout/list_item_cancel.xml
new file mode 100644
index 0000000..4a3c7d8
--- /dev/null
+++ b/tests/autofillservice/res/layout/list_item_cancel.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:textAppearance="?android:attr/textAppearanceListItemSmall"
+ android:gravity="center_vertical"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"/>
+
+ <Button
+ android:id="@+id/cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:text="cancel" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index 691ee97..ecdf90a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -404,6 +404,13 @@
return presentation;
}
+ protected RemoteViews createPresentationWithCancel(String message) {
+ final RemoteViews presentation = new RemoteViews(getContext()
+ .getPackageName(), R.layout.list_item_cancel);
+ presentation.setTextViewText(R.id.text1, message);
+ return presentation;
+ }
+
@NonNull
protected AutofillManager getAutofillManager() {
return mContext.getSystemService(AutofillManager.class);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index ab56c7f..f4e43ef 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -93,6 +93,7 @@
private final UserData mUserData;
private final DoubleVisitor<List<FillContext>, FillResponse.Builder> mVisitor;
private DoubleVisitor<List<FillContext>, SaveInfo.Builder> mSaveInfoVisitor;
+ private final int[] mCancelIds;
private CannedFillResponse(Builder builder) {
mResponseType = builder.mResponseType;
@@ -123,6 +124,7 @@
mUserData = builder.mUserData;
mVisitor = builder.mVisitor;
mSaveInfoVisitor = builder.mSaveInfoVisitor;
+ mCancelIds = builder.mCancelIds;
}
/**
@@ -257,6 +259,7 @@
Log.d(TAG, "Visiting " + builder);
mVisitor.visit(contexts, builder);
}
+ builder.setCancelTargetIds(mCancelIds);
final FillResponse response = builder.build();
Log.v(TAG, "Response: " + response);
@@ -328,6 +331,7 @@
private UserData mUserData;
private DoubleVisitor<List<FillContext>, FillResponse.Builder> mVisitor;
private DoubleVisitor<List<FillContext>, SaveInfo.Builder> mSaveInfoVisitor;
+ private int[] mCancelIds;
public Builder(ResponseType type) {
mResponseType = type;
@@ -526,6 +530,14 @@
mSaveInfoVisitor = visitor;
return this;
}
+
+ /**
+ * Sets targets that cancel current session
+ */
+ public Builder setCancelTargetIds(int[] ids) {
+ mCancelIds = ids;
+ return this;
+ }
}
/**
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FillResponseTest.java b/tests/autofillservice/src/android/autofillservice/cts/FillResponseTest.java
index adae5f7..70f226d 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/FillResponseTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/FillResponseTest.java
@@ -259,5 +259,6 @@
assertThrows(IllegalStateException.class, () -> mBuilder.setHeader(mHeader));
assertThrows(IllegalStateException.class, () -> mBuilder.setFooter(mFooter));
assertThrows(IllegalStateException.class, () -> mBuilder.setUserData(mUserData));
+ assertThrows(IllegalStateException.class, () -> mBuilder.setCancelTargetIds(null));
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index f0bfd39..4684924 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -98,6 +98,7 @@
public static final String ID_OUTPUT = "output";
public static final String ID_STATIC_TEXT = "static_text";
public static final String ID_EMPTY = "empty";
+ public static final String ID_CANCEL = "cancel";
public static final String NULL_DATASET_ID = null;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 507d289..aa60ded 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -20,6 +20,7 @@
import static android.autofillservice.cts.CannedFillResponse.FAIL;
import static android.autofillservice.cts.CannedFillResponse.NO_MOAR_RESPONSES;
import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
+import static android.autofillservice.cts.Helper.ID_CANCEL;
import static android.autofillservice.cts.Helper.ID_EMPTY;
import static android.autofillservice.cts.Helper.ID_PASSWORD;
import static android.autofillservice.cts.Helper.ID_PASSWORD_LABEL;
@@ -2040,7 +2041,6 @@
assertThat(latch.await(500, TimeUnit.SECONDS)).isTrue();
}
-
@Test
public void testContinueStylePositiveSaveButton() throws Exception {
enableService();
@@ -2860,4 +2860,64 @@
mActivity.assertAutoFilled();
mUiBot.assertNoDatasets();
}
+
+ @Test
+ public void testCancelActionButton() throws Exception {
+ // Set service.
+ enableService();
+
+ // Set expectations.
+ final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setField(ID_PASSWORD, "sweet")
+ .setPresentation(createPresentationWithCancel("The Dude"))
+ .build())
+ .setCancelTargetIds(new int[]{R.id.cancel});
+ sReplier.addResponse(builder.build());
+
+ // Trigger auto-fill.
+ mActivity.onUsername(View::requestFocus);
+ sReplier.getNextFillRequest();
+
+ mUiBot.assertDatasetsContains("The Dude");
+
+ // Tap cancel button
+ mUiBot.selectByRelativeId(ID_CANCEL);
+ mUiBot.waitForIdle();
+
+ mUiBot.assertNoDatasets();
+
+ // Test and verify auto-fill does not trigger
+ mActivity.onPassword(View::requestFocus);
+ mUiBot.waitForIdle();
+
+ mUiBot.assertNoDatasetsEver();
+
+ // Test and verify auto-fill does not trigger.
+ mActivity.onUsername(View::requestFocus);
+ mUiBot.waitForIdle();
+
+ mUiBot.assertNoDatasetsEver();
+
+ // Reset
+ mActivity.tapClear();
+
+ // Set expectations.
+ final CannedFillResponse.Builder builder2 = new CannedFillResponse.Builder()
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setField(ID_PASSWORD, "sweet")
+ .setPresentation(createPresentationWithCancel("The Dude"))
+ .build())
+ .setCancelTargetIds(new int[]{R.id.cancel});
+ sReplier.addResponse(builder2.build());
+
+ // Trigger auto-fill.
+ mActivity.onPassword(View::requestFocus);
+ sReplier.getNextFillRequest();
+
+ // Verify auto-fill has been triggered.
+ mUiBot.assertDatasetsContains("The Dude");
+ }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AnrTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AnrTests.java
index ec5456e..e561321 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AnrTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AnrTests.java
@@ -28,6 +28,8 @@
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.server.wm.settings.SettingsSession;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
@@ -57,16 +59,21 @@
public class AnrTests extends ActivityManagerTestBase {
private static final String TAG = "AnrTests";
private LogSeparator mLogSeparator;
+ private SettingsSession<Integer> mHideDialogSetting;
@Before
public void setup() throws Exception {
super.setUp();
mLogSeparator = separateLogs(); // add a new separator for logs
+ mHideDialogSetting = new SettingsSession<>(
+ Settings.Global.getUriFor(Settings.Global.HIDE_ERROR_DIALOGS),
+ Settings.Global::getInt, Settings.Global::putInt);
+ mHideDialogSetting.set(0);
}
-
@After
public void teardown() throws Exception {
+ mHideDialogSetting.close();
stopTestPackage(UNRESPONSIVE_ACTIVITY.getPackageName());
super.tearDown();
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
index 4290ff5..e29b7eb 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
@@ -224,6 +224,7 @@
assertEquals("Double launch sequence must match", expectedTransitions, observedTransitions);
}
+ @FlakyTest(bugId=80414790)
@Test
public void testTopPositionSwitchOnDoubleLaunchAndTopFinish() throws Exception {
final Activity baseActivity = launchActivityAndWait(CallbackTrackingActivity.class);
diff --git a/tests/location/common/src/android/location/cts/common/GetCurrentLocationCapture.java b/tests/location/common/src/android/location/cts/common/GetCurrentLocationCapture.java
new file mode 100644
index 0000000..5e9301d
--- /dev/null
+++ b/tests/location/common/src/android/location/cts/common/GetCurrentLocationCapture.java
@@ -0,0 +1,52 @@
+package android.location.cts.common;
+
+import android.location.Location;
+import android.os.CancellationSignal;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
+
+public class GetCurrentLocationCapture implements Consumer<Location>, AutoCloseable {
+
+ private final CancellationSignal mCancellationSignal;
+ private final CountDownLatch mLatch;
+ private Location mLocation;
+
+ public GetCurrentLocationCapture() {
+ mCancellationSignal = new CancellationSignal();
+ mLatch = new CountDownLatch(1);
+ }
+
+ public CancellationSignal getCancellationSignal() {
+ return mCancellationSignal;
+ }
+
+ public boolean hasLocation(long timeoutMs) throws InterruptedException {
+ return mLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
+ }
+
+ public Location getLocation(long timeoutMs) throws InterruptedException, TimeoutException {
+ if (mLatch.await(timeoutMs, TimeUnit.MILLISECONDS)) {
+ return mLocation;
+ } else {
+ throw new TimeoutException("no location received before timeout");
+ }
+ }
+
+ @Override
+ public void accept(Location location) {
+ if (mLatch.getCount() == 0) {
+ throw new AssertionError("callback received multiple locations");
+ }
+
+ mLocation = location;
+ mLatch.countDown();
+ }
+
+ @Override
+ public void close() {
+ mCancellationSignal.cancel();
+ }
+}
\ No newline at end of file
diff --git a/tests/location/common/src/android/location/cts/common/ProximityPendingIntentCapture.java b/tests/location/common/src/android/location/cts/common/ProximityPendingIntentCapture.java
new file mode 100644
index 0000000..c8f1c06
--- /dev/null
+++ b/tests/location/common/src/android/location/cts/common/ProximityPendingIntentCapture.java
@@ -0,0 +1,63 @@
+package android.location.cts.common;
+
+import static android.location.LocationManager.KEY_PROXIMITY_ENTERING;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.location.LocationManager;
+import android.os.Looper;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class ProximityPendingIntentCapture extends BroadcastReceiver implements AutoCloseable {
+
+ private static final String ACTION = "android.location.cts.LOCATION_BROADCAST";
+ private static final AtomicInteger sRequestCode = new AtomicInteger(0);
+
+ private final Context mContext;
+ private final LocationManager mLocationManager;
+ private final PendingIntent mPendingIntent;
+ private final LinkedBlockingQueue<Boolean> mProximityChanges;
+
+ public ProximityPendingIntentCapture(Context context) {
+ mContext = context;
+ mLocationManager = context.getSystemService(LocationManager.class);
+ mPendingIntent = PendingIntent.getBroadcast(context, sRequestCode.getAndIncrement(),
+ new Intent(ACTION).setPackage(context.getPackageName()),
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ mProximityChanges = new LinkedBlockingQueue<>();
+
+ context.registerReceiver(this, new IntentFilter(ACTION));
+ }
+
+ public PendingIntent getPendingIntent() {
+ return mPendingIntent;
+ }
+
+ public Boolean getNextProximityChange(long timeoutMs) throws InterruptedException {
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ throw new AssertionError("getNextProximityChange() called from main thread");
+ }
+
+ return mProximityChanges.poll(timeoutMs, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public void close() {
+ mLocationManager.removeProximityAlert(mPendingIntent);
+ mContext.unregisterReceiver(this);
+ mPendingIntent.cancel();
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.hasExtra(KEY_PROXIMITY_ENTERING)) {
+ mProximityChanges.add(intent.getBooleanExtra(KEY_PROXIMITY_ENTERING, false));
+ }
+ }
+}
diff --git a/tests/location/location_fine/src/android/location/cts/fine/AddressTest.java b/tests/location/location_fine/src/android/location/cts/fine/AddressTest.java
index 00118c9..a17755a 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/AddressTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/AddressTest.java
@@ -16,18 +16,30 @@
package android.location.cts.fine;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import java.util.Locale;
-import junit.framework.TestCase;
import android.location.Address;
import android.os.Bundle;
import android.os.Parcel;
-import android.os.Parcelable;
-/**
- * Test the main functionalities of the AddressTest.
- */
-public class AddressTest extends TestCase {
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class AddressTest {
+
+ private static final double DELTA = 0.001;
+
+ @Test
public void testConstructor() {
new Address(Locale.ENGLISH);
@@ -36,18 +48,7 @@
new Address(null);
}
- public void testDescribeContents() {
- Address address = new Address(Locale.GERMAN);
-
- assertEquals(0, address.describeContents());
-
- Bundle extras = new Bundle();
- extras.putParcelable("key1", new MockParcelable());
- address.setExtras(extras);
-
- assertEquals(extras.describeContents(), address.describeContents());
- }
-
+ @Test
public void testAccessAdminArea() {
Address address = new Address(Locale.ITALY);
@@ -59,6 +60,7 @@
assertNull(address.getAdminArea());
}
+ @Test
public void testAccessCountryCode() {
Address address = new Address(Locale.JAPAN);
@@ -70,6 +72,7 @@
assertNull(address.getCountryCode());
}
+ @Test
public void testAccessCountryName() {
Address address = new Address(Locale.KOREA);
@@ -81,6 +84,7 @@
assertNull(address.getCountryName());
}
+ @Test
public void testAccessExtras() {
Address address = new Address(Locale.TAIWAN);
@@ -98,6 +102,7 @@
assertNull(address.getExtras());
}
+ @Test
public void testAccessFeatureName() {
Address address = new Address(Locale.SIMPLIFIED_CHINESE);
@@ -109,6 +114,7 @@
assertNull(address.getFeatureName());
}
+ @Test
public void testAccessLatitude() {
Address address = new Address(Locale.CHINA);
assertFalse(address.hasLatitude());
@@ -116,7 +122,7 @@
double latitude = 1.23456789;
address.setLatitude(latitude);
assertTrue(address.hasLatitude());
- assertEquals(latitude, address.getLatitude());
+ assertEquals(latitude, address.getLatitude(), DELTA);
address.clearLatitude();
assertFalse(address.hasLatitude());
@@ -124,9 +130,11 @@
address.getLatitude();
fail("should throw IllegalStateException.");
} catch (IllegalStateException e) {
+ // pass
}
}
+ @Test
public void testAccessLongitude() {
Address address = new Address(Locale.CHINA);
assertFalse(address.hasLongitude());
@@ -134,7 +142,7 @@
double longitude = 1.23456789;
address.setLongitude(longitude);
assertTrue(address.hasLongitude());
- assertEquals(longitude, address.getLongitude());
+ assertEquals(longitude, address.getLongitude(), DELTA);
address.clearLongitude();
assertFalse(address.hasLongitude());
@@ -142,9 +150,11 @@
address.getLongitude();
fail("should throw IllegalStateException.");
} catch (IllegalStateException e) {
+ // pass
}
}
+ @Test
public void testAccessPhone() {
Address address = new Address(Locale.CHINA);
@@ -156,6 +166,7 @@
assertNull(address.getPhone());
}
+ @Test
public void testAccessPostalCode() {
Address address = new Address(Locale.CHINA);
@@ -167,6 +178,7 @@
assertNull(address.getPostalCode());
}
+ @Test
public void testAccessThoroughfare() {
Address address = new Address(Locale.CHINA);
@@ -178,6 +190,7 @@
assertNull(address.getThoroughfare());
}
+ @Test
public void testAccessUrl() {
Address address = new Address(Locale.CHINA);
@@ -189,6 +202,7 @@
assertNull(address.getUrl());
}
+ @Test
public void testAccessSubAdminArea() {
Address address = new Address(Locale.CHINA);
@@ -200,6 +214,7 @@
assertNull(address.getSubAdminArea());
}
+ @Test
public void testToString() {
Address address = new Address(Locale.CHINA);
@@ -212,6 +227,7 @@
assertEquals(expected, address.toString());
}
+ @Test
public void testAddressLine() {
Address address = new Address(Locale.CHINA);
@@ -219,12 +235,14 @@
address.setAddressLine(-1, null);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
try {
address.getAddressLine(-1);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
address.setAddressLine(0, null);
@@ -246,6 +264,7 @@
assertEquals(5, address.getMaxAddressLineIndex());
}
+ @Test
public void testGetLocale() {
Locale locale = Locale.US;
Address address = new Address(locale);
@@ -259,6 +278,7 @@
assertNull(address.getLocale());
}
+ @Test
public void testAccessLocality() {
Address address = new Address(Locale.PRC);
@@ -270,6 +290,7 @@
assertNull(address.getLocality());
}
+ @Test
public void testAccessPremises() {
Address address = new Address(Locale.PRC);
@@ -281,6 +302,7 @@
assertNull(address.getPremises());
}
+ @Test
public void testAccessSubLocality() {
Address address = new Address(Locale.PRC);
@@ -292,6 +314,7 @@
assertNull(address.getSubLocality());
}
+ @Test
public void testAccessSubThoroughfare() {
Address address = new Address(Locale.PRC);
@@ -303,6 +326,7 @@
assertNull(address.getSubThoroughfare());
}
+ @Test
public void testWriteToParcel() {
Locale locale = Locale.KOREA;
Address address = new Address(locale);
@@ -332,13 +356,4 @@
parcel.recycle();
}
-
- private class MockParcelable implements Parcelable {
- public int describeContents() {
- return Parcelable.CONTENTS_FILE_DESCRIPTOR;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
- }
}
diff --git a/tests/location/location_fine/src/android/location/cts/fine/CriteriaTest.java b/tests/location/location_fine/src/android/location/cts/fine/CriteriaTest.java
index 43ce33f..33686ea 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/CriteriaTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/CriteriaTest.java
@@ -17,11 +17,23 @@
package android.location.cts.fine;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import android.location.Criteria;
import android.os.Parcel;
-import android.test.AndroidTestCase;
-public class CriteriaTest extends AndroidTestCase {
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CriteriaTest {
+
+ @Test
public void testConstructor() {
new Criteria();
@@ -48,11 +60,13 @@
}
}
+ @Test
public void testDescribeContents() {
Criteria criteria = new Criteria();
criteria.describeContents();
}
+ @Test
public void testAccessAccuracy() {
Criteria criteria = new Criteria();
@@ -79,6 +93,7 @@
}
}
+ @Test
public void testAccessPowerRequirement() {
Criteria criteria = new Criteria();
@@ -103,6 +118,7 @@
}
}
+ @Test
public void testAccessAltitudeRequired() {
Criteria criteria = new Criteria();
@@ -113,6 +129,7 @@
assertTrue(criteria.isAltitudeRequired());
}
+ @Test
public void testAccessBearingAccuracy() {
Criteria criteria = new Criteria();
@@ -126,6 +143,7 @@
assertEquals(Criteria.NO_REQUIREMENT, criteria.getBearingAccuracy());
}
+ @Test
public void testAccessBearingRequired() {
Criteria criteria = new Criteria();
@@ -136,6 +154,7 @@
assertTrue(criteria.isBearingRequired());
}
+ @Test
public void testAccessCostAllowed() {
Criteria criteria = new Criteria();
@@ -146,6 +165,7 @@
assertTrue(criteria.isCostAllowed());
}
+ @Test
public void testAccessHorizontalAccuracy() {
Criteria criteria = new Criteria();
@@ -162,6 +182,7 @@
assertEquals(Criteria.NO_REQUIREMENT, criteria.getHorizontalAccuracy());
}
+ @Test
public void testAccessSpeedAccuracy() {
Criteria criteria = new Criteria();
@@ -185,6 +206,7 @@
assertTrue(criteria.isSpeedRequired());
}
+ @Test
public void testAccessVerticalAccuracy() {
Criteria criteria = new Criteria();
@@ -198,6 +220,7 @@
assertEquals(Criteria.NO_REQUIREMENT, criteria.getVerticalAccuracy());
}
+ @Test
public void testWriteToParcel() {
Criteria criteria = new Criteria();
criteria.setAltitudeRequired(true);
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java b/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
index 1aef76a..69b1f0c 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
@@ -17,54 +17,64 @@
package android.location.cts.fine;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Geocoder;
-import android.test.AndroidTestCase;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.Locale;
-public class GeocoderTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class GeocoderTest {
- private static final int MAX_NUM_RETRIES = 5;
- private static final int TIME_BETWEEN_RETRIES_MS = 10 * 1000;
+ private static final int MAX_NUM_RETRIES = 2;
+ private static final int TIME_BETWEEN_RETRIES_MS = 2000;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = ApplicationProvider.getApplicationContext();
+ }
+
+ @Test
public void testConstructor() {
- new Geocoder(getContext());
+ new Geocoder(mContext);
- new Geocoder(getContext(), Locale.ENGLISH);
+ new Geocoder(mContext, Locale.ENGLISH);
try {
- new Geocoder(getContext(), null);
+ new Geocoder(mContext, null);
fail("should throw NullPointerException.");
} catch (NullPointerException e) {
// expected.
}
}
+ @Test
public void testIsPresent() {
- Geocoder geocoder = new Geocoder(getContext());
if (isServiceMissing()) {
- assertFalse(geocoder.isPresent());
+ assertFalse(Geocoder.isPresent());
} else {
- assertTrue(geocoder.isPresent());
+ assertTrue(Geocoder.isPresent());
}
}
- private boolean isServiceMissing() {
- Context context = getContext();
- PackageManager pm = context.getPackageManager();
-
- final Intent intent = new Intent("com.android.location.service.GeocodeProvider");
- final int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
- return pm.queryIntentServices(intent, flags).isEmpty();
- }
-
+ @Test
public void testGetFromLocation() throws IOException, InterruptedException {
- Geocoder geocoder = new Geocoder(getContext());
+ Geocoder geocoder = new Geocoder(mContext);
// There is no guarantee that geocoder.getFromLocation returns accurate results
// Thus only test that calling the method with valid arguments doesn't produce
@@ -92,6 +102,7 @@
geocoder.getFromLocation(-91, 30, 5);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
try {
@@ -99,6 +110,7 @@
geocoder.getFromLocation(91, 30, 5);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
try {
@@ -106,6 +118,7 @@
geocoder.getFromLocation(10, -181, 5);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
try {
@@ -113,11 +126,13 @@
geocoder.getFromLocation(10, 181, 5);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
}
+ @Test
public void testGetFromLocationName() throws IOException, InterruptedException {
- Geocoder geocoder = new Geocoder(getContext(), Locale.US);
+ Geocoder geocoder = new Geocoder(mContext, Locale.US);
// There is no guarantee that geocoder.getFromLocationName returns accurate results.
// Thus only test that calling the method with valid arguments doesn't produce
@@ -143,30 +158,44 @@
geocoder.getFromLocationName(null, 5);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
try {
geocoder.getFromLocationName("Beijing", 5, -91, 100, 45, 130);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
try {
geocoder.getFromLocationName("Beijing", 5, 25, 190, 45, 130);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
try {
geocoder.getFromLocationName("Beijing", 5, 25, 100, 91, 130);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
try {
geocoder.getFromLocationName("Beijing", 5, 25, 100, 45, -181);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
+ // pass
}
}
+
+ private boolean isServiceMissing() {
+ PackageManager pm = mContext.getPackageManager();
+
+ final Intent intent = new Intent("com.android.location.service.GeocodeProvider");
+ final int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+ return pm.queryIntentServices(intent, flags).isEmpty();
+ }
}
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GnssClockTest.java b/tests/location/location_fine/src/android/location/cts/fine/GnssClockTest.java
index b1d3913..7863675 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GnssClockTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GnssClockTest.java
@@ -16,49 +16,24 @@
package android.location.cts.fine;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
import android.location.GnssClock;
-import android.location.cts.common.GnssTestCase;
import android.os.Parcel;
-public class GnssClockTest extends GnssTestCase {
- public void testDescribeContents() {
- GnssClock clock = new GnssClock();
- clock.describeContents();
- }
+import androidx.test.ext.junit.runners.AndroidJUnit4;
- public void testReset() {
- GnssClock clock = new GnssClock();
- clock.reset();
- }
+import org.junit.Test;
+import org.junit.runner.RunWith;
- private static void setTestValues(GnssClock clock) {
- clock.setBiasNanos(1.0);
- clock.setBiasUncertaintyNanos(2.0);
- clock.setDriftNanosPerSecond(3.0);
- clock.setDriftUncertaintyNanosPerSecond(4.0);
- clock.setFullBiasNanos(5);
- clock.setHardwareClockDiscontinuityCount(6);
- clock.setLeapSecond(7);
- clock.setTimeNanos(8);
- clock.setTimeUncertaintyNanos(9.0);
- clock.setElapsedRealtimeNanos(10987732253L);
- clock.setElapsedRealtimeUncertaintyNanos(3943523.0);
- }
+@RunWith(AndroidJUnit4.class)
+public class GnssClockTest {
- private static void verifyTestValues(GnssClock clock) {
- assertEquals(1.0, clock.getBiasNanos());
- assertEquals(2.0, clock.getBiasUncertaintyNanos());
- assertEquals(3.0, clock.getDriftNanosPerSecond());
- assertEquals(4.0, clock.getDriftUncertaintyNanosPerSecond());
- assertEquals(5, clock.getFullBiasNanos());
- assertEquals(6, clock.getHardwareClockDiscontinuityCount());
- assertEquals(7, clock.getLeapSecond());
- assertEquals(8, clock.getTimeNanos());
- assertEquals(9.0, clock.getTimeUncertaintyNanos());
- assertEquals(10987732253L, clock.getElapsedRealtimeNanos());
- assertEquals(3943523.0, clock.getElapsedRealtimeUncertaintyNanos());
- }
+ private static final double DELTA = 0.001;
+ @Test
public void testWriteToParcel() {
GnssClock clock = new GnssClock();
setTestValues(clock);
@@ -70,6 +45,13 @@
parcel.recycle();
}
+ @Test
+ public void testReset() {
+ GnssClock clock = new GnssClock();
+ clock.reset();
+ }
+
+ @Test
public void testSet() {
GnssClock clock = new GnssClock();
setTestValues(clock);
@@ -78,6 +60,7 @@
verifyTestValues(newClock);
}
+ @Test
public void testHasAndReset() {
GnssClock clock = new GnssClock();
setTestValues(clock);
@@ -118,4 +101,32 @@
clock.resetElapsedRealtimeUncertaintyNanos();
assertFalse(clock.hasElapsedRealtimeUncertaintyNanos());
}
+
+ private static void setTestValues(GnssClock clock) {
+ clock.setBiasNanos(1.0);
+ clock.setBiasUncertaintyNanos(2.0);
+ clock.setDriftNanosPerSecond(3.0);
+ clock.setDriftUncertaintyNanosPerSecond(4.0);
+ clock.setFullBiasNanos(5);
+ clock.setHardwareClockDiscontinuityCount(6);
+ clock.setLeapSecond(7);
+ clock.setTimeNanos(8);
+ clock.setTimeUncertaintyNanos(9.0);
+ clock.setElapsedRealtimeNanos(10987732253L);
+ clock.setElapsedRealtimeUncertaintyNanos(3943523.0);
+ }
+
+ private static void verifyTestValues(GnssClock clock) {
+ assertEquals(1.0, clock.getBiasNanos(), DELTA);
+ assertEquals(2.0, clock.getBiasUncertaintyNanos(), DELTA);
+ assertEquals(3.0, clock.getDriftNanosPerSecond(), DELTA);
+ assertEquals(4.0, clock.getDriftUncertaintyNanosPerSecond(), DELTA);
+ assertEquals(5, clock.getFullBiasNanos());
+ assertEquals(6, clock.getHardwareClockDiscontinuityCount());
+ assertEquals(7, clock.getLeapSecond());
+ assertEquals(8, clock.getTimeNanos());
+ assertEquals(9.0, clock.getTimeUncertaintyNanos(), DELTA);
+ assertEquals(10987732253L, clock.getElapsedRealtimeNanos());
+ assertEquals(3943523.0, clock.getElapsedRealtimeUncertaintyNanos(), DELTA);
+ }
}
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementTest.java b/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementTest.java
index d9cc90e..2ed4f1d 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementTest.java
@@ -16,67 +16,37 @@
package android.location.cts.fine;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
import android.location.GnssMeasurement;
import android.location.GnssStatus;
-import android.location.cts.common.GnssTestCase;
import android.os.Parcel;
-public class GnssMeasurementTest extends GnssTestCase {
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class GnssMeasurementTest {
+
+ private static final double DELTA = 0.001;
+
+ @Test
public void testDescribeContents() {
GnssMeasurement measurement = new GnssMeasurement();
- measurement.describeContents();
+ assertEquals(0, measurement.describeContents());
}
+ @Test
public void testReset() {
GnssMeasurement measurement = new GnssMeasurement();
measurement.reset();
}
- private static void setTestValues(GnssMeasurement measurement) {
- measurement.setAccumulatedDeltaRangeMeters(1.0);
- measurement.setAccumulatedDeltaRangeState(2);
- measurement.setAccumulatedDeltaRangeUncertaintyMeters(3.0);
- measurement.setCarrierCycles(4);
- measurement.setCarrierFrequencyHz(5.0f);
- measurement.setCarrierPhase(6.0);
- measurement.setCarrierPhaseUncertainty(7.0);
- measurement.setCn0DbHz(8.0);
- measurement.setCodeType("C");
- measurement.setConstellationType(GnssStatus.CONSTELLATION_GALILEO);
- measurement.setMultipathIndicator(GnssMeasurement.MULTIPATH_INDICATOR_DETECTED);
- measurement.setPseudorangeRateMetersPerSecond(9.0);
- measurement.setPseudorangeRateUncertaintyMetersPerSecond(10.0);
- measurement.setReceivedSvTimeNanos(11);
- measurement.setReceivedSvTimeUncertaintyNanos(12);
- measurement.setSnrInDb(13.0);
- measurement.setState(14);
- measurement.setSvid(15);
- measurement.setTimeOffsetNanos(16.0);
- }
-
- private static void verifyTestValues(GnssMeasurement measurement) {
- assertEquals(1.0, measurement.getAccumulatedDeltaRangeMeters());
- assertEquals(2, measurement.getAccumulatedDeltaRangeState());
- assertEquals(3.0, measurement.getAccumulatedDeltaRangeUncertaintyMeters());
- assertEquals(4, measurement.getCarrierCycles());
- assertEquals(5.0f, measurement.getCarrierFrequencyHz());
- assertEquals(6.0, measurement.getCarrierPhase());
- assertEquals(7.0, measurement.getCarrierPhaseUncertainty());
- assertEquals(8.0, measurement.getCn0DbHz());
- assertEquals(GnssStatus.CONSTELLATION_GALILEO, measurement.getConstellationType());
- assertEquals(GnssMeasurement.MULTIPATH_INDICATOR_DETECTED,
- measurement.getMultipathIndicator());
- assertEquals("C", measurement.getCodeType());
- assertEquals(9.0, measurement.getPseudorangeRateMetersPerSecond());
- assertEquals(10.0, measurement.getPseudorangeRateUncertaintyMetersPerSecond());
- assertEquals(11, measurement.getReceivedSvTimeNanos());
- assertEquals(12, measurement.getReceivedSvTimeUncertaintyNanos());
- assertEquals(13.0, measurement.getSnrInDb());
- assertEquals(14, measurement.getState());
- assertEquals(15, measurement.getSvid());
- assertEquals(16.0, measurement.getTimeOffsetNanos());
- }
-
+ @Test
public void testWriteToParcel() {
GnssMeasurement measurement = new GnssMeasurement();
setTestValues(measurement);
@@ -88,6 +58,7 @@
parcel.recycle();
}
+ @Test
public void testSet() {
GnssMeasurement measurement = new GnssMeasurement();
setTestValues(measurement);
@@ -96,6 +67,7 @@
verifyTestValues(newMeasurement);
}
+ @Test
public void testSetReset() {
GnssMeasurement measurement = new GnssMeasurement();
setTestValues(measurement);
@@ -124,4 +96,49 @@
measurement.resetCodeType();
assertFalse(measurement.hasCodeType());
}
+
+ private static void setTestValues(GnssMeasurement measurement) {
+ measurement.setAccumulatedDeltaRangeMeters(1.0);
+ measurement.setAccumulatedDeltaRangeState(2);
+ measurement.setAccumulatedDeltaRangeUncertaintyMeters(3.0);
+ measurement.setCarrierCycles(4);
+ measurement.setCarrierFrequencyHz(5.0f);
+ measurement.setCarrierPhase(6.0);
+ measurement.setCarrierPhaseUncertainty(7.0);
+ measurement.setCn0DbHz(8.0);
+ measurement.setCodeType("C");
+ measurement.setConstellationType(GnssStatus.CONSTELLATION_GALILEO);
+ measurement.setMultipathIndicator(GnssMeasurement.MULTIPATH_INDICATOR_DETECTED);
+ measurement.setPseudorangeRateMetersPerSecond(9.0);
+ measurement.setPseudorangeRateUncertaintyMetersPerSecond(10.0);
+ measurement.setReceivedSvTimeNanos(11);
+ measurement.setReceivedSvTimeUncertaintyNanos(12);
+ measurement.setSnrInDb(13.0);
+ measurement.setState(14);
+ measurement.setSvid(15);
+ measurement.setTimeOffsetNanos(16.0);
+ }
+
+ private static void verifyTestValues(GnssMeasurement measurement) {
+ assertEquals(1.0, measurement.getAccumulatedDeltaRangeMeters(), DELTA);
+ assertEquals(2, measurement.getAccumulatedDeltaRangeState());
+ assertEquals(3.0, measurement.getAccumulatedDeltaRangeUncertaintyMeters(), DELTA);
+ assertEquals(4, measurement.getCarrierCycles());
+ assertEquals(5.0f, measurement.getCarrierFrequencyHz(), DELTA);
+ assertEquals(6.0, measurement.getCarrierPhase(), DELTA);
+ assertEquals(7.0, measurement.getCarrierPhaseUncertainty(), DELTA);
+ assertEquals(8.0, measurement.getCn0DbHz(), DELTA);
+ assertEquals(GnssStatus.CONSTELLATION_GALILEO, measurement.getConstellationType());
+ assertEquals(GnssMeasurement.MULTIPATH_INDICATOR_DETECTED,
+ measurement.getMultipathIndicator());
+ assertEquals("C", measurement.getCodeType());
+ assertEquals(9.0, measurement.getPseudorangeRateMetersPerSecond(), DELTA);
+ assertEquals(10.0, measurement.getPseudorangeRateUncertaintyMetersPerSecond(), DELTA);
+ assertEquals(11, measurement.getReceivedSvTimeNanos());
+ assertEquals(12, measurement.getReceivedSvTimeUncertaintyNanos());
+ assertEquals(13.0, measurement.getSnrInDb(), DELTA);
+ assertEquals(14, measurement.getState());
+ assertEquals(15, measurement.getSvid());
+ assertEquals(16.0, measurement.getTimeOffsetNanos(), DELTA);
+ }
}
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementsEventTest.java b/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementsEventTest.java
index 6ff29b2..048c741 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementsEventTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementsEventTest.java
@@ -16,26 +16,36 @@
package android.location.cts.fine;
+import static org.junit.Assert.assertEquals;
+
import android.location.GnssClock;
import android.location.GnssMeasurement;
import android.location.GnssMeasurementsEvent;
import android.location.GnssStatus;
-import android.location.cts.common.GnssTestCase;
import android.os.Parcel;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.Collection;
import java.util.Iterator;
-public class GnssMeasurementsEventTest extends GnssTestCase {
+@RunWith(AndroidJUnit4.class)
+public class GnssMeasurementsEventTest {
+
+ @Test
public void testDescribeContents() {
GnssClock clock = new GnssClock();
GnssMeasurement m1 = new GnssMeasurement();
GnssMeasurement m2 = new GnssMeasurement();
GnssMeasurementsEvent event = new GnssMeasurementsEvent(
clock, new GnssMeasurement[] {m1, m2});
- event.describeContents();
+ assertEquals(0, event.describeContents());
}
+ @Test
public void testWriteToParcel() {
GnssClock clock = new GnssClock();
clock.setLeapSecond(100);
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
index eb445ce..c57107d 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
@@ -18,9 +18,6 @@
import static android.location.LocationManager.FUSED_PROVIDER;
import static android.location.LocationManager.GPS_PROVIDER;
-import static android.location.LocationManager.KEY_LOCATION_CHANGED;
-import static android.location.LocationManager.KEY_PROVIDER_ENABLED;
-import static android.location.LocationManager.KEY_PROXIMITY_ENTERING;
import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.location.LocationManager.PASSIVE_PROVIDER;
@@ -53,13 +50,16 @@
import android.location.LocationProvider;
import android.location.LocationRequest;
import android.location.OnNmeaMessageListener;
-import android.os.Bundle;
-import android.os.CancellationSignal;
+import android.location.cts.common.GetCurrentLocationCapture;
+import android.location.cts.common.LocationListenerCapture;
+import android.location.cts.common.LocationPendingIntentCapture;
+import android.location.cts.common.ProximityPendingIntentCapture;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.UserManager;
import android.platform.test.annotations.AppModeFull;
-import android.provider.Settings;
import android.provider.Settings.Secure;
import android.util.Log;
@@ -68,7 +68,6 @@
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.LocationUtils;
-import com.android.internal.util.Preconditions;
import org.junit.After;
import org.junit.Before;
@@ -77,11 +76,9 @@
import java.util.List;
import java.util.Random;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
@RunWith(AndroidJUnit4.class)
public class LocationManagerFineTest {
@@ -199,11 +196,9 @@
mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
Executors.newSingleThreadExecutor(), capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc);
- assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc);
+ assertThat(capture.getLocation(TIMEOUT_MS)).isEqualTo(loc);
}
- // TODO: test timeout case
-
try {
mManager.getCurrentLocation((String) null, null, Executors.newSingleThreadExecutor(),
(location) -> {});
@@ -221,7 +216,7 @@
mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
Runnable::run, capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc);
- assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc);
+ assertThat(capture.getLocation(TIMEOUT_MS)).isEqualTo(loc);
}
}
@@ -234,7 +229,7 @@
Runnable::run, capture);
capture.getCancellationSignal().cancel();
mManager.setTestProviderLocation(TEST_PROVIDER, loc);
- assertNull(capture.getNextLocation(FAILURE_TIMEOUT_MS));
+ assertFalse(capture.hasLocation(FAILURE_TIMEOUT_MS));
}
}
@@ -244,14 +239,14 @@
mManager.setTestProviderEnabled(TEST_PROVIDER, false);
mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
Runnable::run, capture);
- assertNull(capture.getNextLocation(FAILURE_TIMEOUT_MS));
+ assertNull(capture.getLocation(FAILURE_TIMEOUT_MS));
}
try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
Runnable::run, capture);
mManager.setTestProviderEnabled(TEST_PROVIDER, false);
- assertNull(capture.getNextLocation(FAILURE_TIMEOUT_MS));
+ assertNull(capture.getLocation(FAILURE_TIMEOUT_MS));
}
}
@@ -260,7 +255,7 @@
Location loc1 = createLocation(TEST_PROVIDER, mRandom);
Location loc2 = createLocation(TEST_PROVIDER, mRandom);
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
Executors.newSingleThreadExecutor(), capture);
@@ -290,14 +285,14 @@
// expected
}
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, null, capture);
fail("Should throw IllegalArgumentException if executor is null!");
} catch (IllegalArgumentException e) {
// expected
}
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(null, 0, 0, capture);
fail("Should throw IllegalArgumentException if provider is null!");
} catch (IllegalArgumentException e) {
@@ -366,7 +361,7 @@
Location loc1 = createLocation(TEST_PROVIDER, mRandom);
Location loc2 = createLocation(TEST_PROVIDER, mRandom);
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, Runnable::run, capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
@@ -390,7 +385,7 @@
Location loc1 = createLocation(TEST_PROVIDER, mRandom);
Location loc2 = createLocation(TEST_PROVIDER, mRandom);
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, capture, looper);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
@@ -421,7 +416,7 @@
true,
Criteria.POWER_LOW,
Criteria.ACCURACY_FINE);
- mManager.setTestProviderEnabled(FUSED_PROVIDER, true);
+ setTestProviderEnabled(FUSED_PROVIDER, true);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
@@ -430,7 +425,7 @@
Location loc1 = createLocation(FUSED_PROVIDER, mRandom);
Location loc2 = createLocation(FUSED_PROVIDER, mRandom);
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(0, 0, criteria, Runnable::run, capture);
mManager.setTestProviderLocation(FUSED_PROVIDER, loc1);
@@ -460,14 +455,14 @@
// expected
}
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(0, 0, criteria, null, capture);
fail("Should throw IllegalArgumentException if executor is null!");
} catch (IllegalArgumentException e) {
// expected
}
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(0, 0, null, Runnable::run, capture);
fail("Should throw IllegalArgumentException if criteria is null!");
} catch (IllegalArgumentException e) {
@@ -480,7 +475,7 @@
Location loc1 = createLocation(TEST_PROVIDER, mRandom);
Location loc2 = createLocation(TEST_PROVIDER, mRandom);
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(TEST_PROVIDER, 1000, 1000, Runnable::run, capture);
mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, Runnable::run, capture);
@@ -500,7 +495,7 @@
false);
request.setNumUpdates(1);
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(request, Runnable::run, capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
@@ -518,7 +513,7 @@
LocationRequest request = LocationRequest.createFromDeprecatedProvider(TEST_PROVIDER, 5000,
0, false);
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(request, Runnable::run, capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
@@ -536,7 +531,7 @@
LocationRequest request = LocationRequest.createFromDeprecatedProvider(TEST_PROVIDER, 0,
200000, false);
- try (LocationListenerCapture capture = new LocationListenerCapture(mManager)) {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
mManager.requestLocationUpdates(request, Runnable::run, capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
@@ -547,6 +542,42 @@
}
@Test
+ @AppModeFull(reason = "Instant apps can't hold ACCESS_LOCATION_EXTRA_COMMANDS permission")
+ public void testRequestGpsUpdates_B9758659() throws Exception {
+ // test for b/9758659, where the gps provider may reuse network provider positions creating
+ // an unnatural feedback loop
+ assertTrue(mManager.isProviderEnabled(GPS_PROVIDER));
+
+ Location networkLocation = createLocation(NETWORK_PROVIDER, mRandom);
+
+ mManager.addTestProvider(NETWORK_PROVIDER,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ Criteria.POWER_LOW,
+ Criteria.ACCURACY_COARSE);
+ setTestProviderEnabled(NETWORK_PROVIDER, true);
+ mManager.setTestProviderLocation(NETWORK_PROVIDER, networkLocation);
+
+ // reset gps provider to give it a cold start scenario
+ mManager.sendExtraCommand(GPS_PROVIDER, "delete_aiding_data", null);
+
+ LocationRequest request = LocationRequest.createFromDeprecatedProvider(GPS_PROVIDER, 0, 0, false);
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
+ mManager.requestLocationUpdates(request, Runnable::run, capture);
+
+ Location location = capture.getNextLocation(TIMEOUT_MS);
+ if (location != null) {
+ assertThat(location.distanceTo(networkLocation)).isGreaterThan(1000.0f);
+ }
+ }
+ }
+
+ @Test
public void testGetAllProviders() {
List<String> providers = mManager.getAllProviders();
if (hasGpsFeature()) {
@@ -563,14 +594,14 @@
}
@Test
- public void testGetProviders() {
+ public void testGetProviders() throws Exception {
List<String> providers = mManager.getProviders(false);
assertTrue(providers.contains(TEST_PROVIDER));
providers = mManager.getProviders(true);
assertTrue(providers.contains(TEST_PROVIDER));
- mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+ setTestProviderEnabled(TEST_PROVIDER, false);
providers = mManager.getProviders(false);
assertTrue(providers.contains(TEST_PROVIDER));
@@ -599,7 +630,7 @@
}
@Test
- public void testGetBestProvider() {
+ public void testGetBestProvider() throws Exception {
List<String> allProviders = mManager.getAllProviders();
Criteria criteria = new Criteria();
@@ -629,7 +660,7 @@
criteria.setPowerRequirement(Criteria.POWER_LOW);
assertThat(mManager.getBestProvider(criteria, false)).isEqualTo(TEST_PROVIDER);
- mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+ setTestProviderEnabled(TEST_PROVIDER, false);
assertNotEquals(TEST_PROVIDER, mManager.getBestProvider(criteria, true));
}
@@ -656,7 +687,7 @@
}
@Test
- @AppModeFull(reason = "Instant apps can't hold ACCESS_LOCATION_EXTRA_COMMANDS")
+ @AppModeFull(reason = "Instant apps can't hold ACCESS_LOCATION_EXTRA_COMMANDS permission")
public void testSendExtraCommand() {
for (String provider : mManager.getAllProviders()) {
boolean res = mManager.sendExtraCommand(provider, "dontCrash", null);
@@ -743,12 +774,12 @@
Runnable::run, capture);
mManager.setTestProviderLocation(provider, loc1);
- Location received = capture.getNextLocation(TIMEOUT_MS);
+ Location received = capture.getLocation(TIMEOUT_MS);
assertThat(received).isEqualTo(loc1);
assertTrue(received.isFromMockProvider());
assertThat(mManager.getLastKnownLocation(provider)).isEqualTo(loc1);
- mManager.setTestProviderEnabled(provider, false);
+ setTestProviderEnabled(provider, false);
mManager.setTestProviderLocation(provider, loc2);
assertNull(mManager.getLastKnownLocation(provider));
}
@@ -812,7 +843,7 @@
Runnable::run, capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc);
- Location received = capture.getNextLocation(TIMEOUT_MS);
+ Location received = capture.getLocation(TIMEOUT_MS);
assertThat(received).isEqualTo(loc);
assertTrue(received.isFromMockProvider());
@@ -853,7 +884,7 @@
false,
Criteria.POWER_MEDIUM,
Criteria.ACCURACY_FINE);
- mManager.setTestProviderEnabled(FUSED_PROVIDER, true);
+ setTestProviderEnabled(FUSED_PROVIDER, true);
mManager.setTestProviderLocation(FUSED_PROVIDER, createLocation(FUSED_PROVIDER, 30, 30, 10));
try (ProximityPendingIntentCapture capture = new ProximityPendingIntentCapture(mContext)) {
@@ -919,7 +950,7 @@
false,
Criteria.POWER_MEDIUM,
Criteria.ACCURACY_FINE);
- mManager.setTestProviderEnabled(FUSED_PROVIDER, true);
+ setTestProviderEnabled(FUSED_PROVIDER, true);
mManager.setTestProviderLocation(FUSED_PROVIDER, createLocation(FUSED_PROVIDER, 0, 0, 10));
try (ProximityPendingIntentCapture capture = new ProximityPendingIntentCapture(mContext)) {
@@ -945,7 +976,7 @@
false,
Criteria.POWER_MEDIUM,
Criteria.ACCURACY_FINE);
- mManager.setTestProviderEnabled(FUSED_PROVIDER, true);
+ setTestProviderEnabled(FUSED_PROVIDER, true);
mManager.setTestProviderLocation(FUSED_PROVIDER, createLocation(FUSED_PROVIDER, 30, 30, 10));
try (ProximityPendingIntentCapture capture = new ProximityPendingIntentCapture(mContext)) {
@@ -1017,190 +1048,28 @@
return !mContext.getSystemService(UserManager.class).isSystemUser();
}
- private static class LocationListenerCapture implements LocationListener, AutoCloseable {
+ private void setTestProviderEnabled(String provider, boolean enabled) throws InterruptedException {
+ // prior to R, setTestProviderEnabled is asynchronous, so we have to wait for provider
+ // state to settle.
+ if (VERSION.SDK_INT <= VERSION_CODES.Q) {
+ CountDownLatch latch = new CountDownLatch(1);
+ BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ latch.countDown();
+ }
+ };
+ mContext.registerReceiver(receiver,
+ new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION));
+ mManager.setTestProviderEnabled(provider, enabled);
- private final LocationManager mLocationManager;
- private final LinkedBlockingQueue<Location> mLocations;
- private final LinkedBlockingQueue<Boolean> mProviderChanges;
-
- public LocationListenerCapture(LocationManager locationManager) {
- mLocationManager = locationManager;
- mLocations = new LinkedBlockingQueue<>();
- mProviderChanges = new LinkedBlockingQueue<>();
- }
-
- public Location getNextLocation(long timeoutMs) throws InterruptedException {
- return mLocations.poll(timeoutMs, TimeUnit.MILLISECONDS);
- }
-
- public Boolean getNextProviderChange(long timeoutMs) throws InterruptedException {
- return mProviderChanges.poll(timeoutMs, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public void onLocationChanged(Location location) {
- mLocations.add(location);
- }
-
- @Override
- public void onStatusChanged(String provider, int status, Bundle extras) {
- }
-
- @Override
- public void onProviderEnabled(String provider) {
- mProviderChanges.add(true);
- }
-
- @Override
- public void onProviderDisabled(String provider) {
- mProviderChanges.add(false);
- }
-
- @Override
- public void close() {
- mLocationManager.removeUpdates(this);
- }
- }
-
- private static class LocationPendingIntentCapture extends BroadcastReceiver implements
- AutoCloseable {
-
- private static final String ACTION = "android.location.cts.LOCATION_BROADCAST";
- private static final AtomicInteger sRequestCode = new AtomicInteger(0);
-
- private final Context mContext;
- private final LocationManager mLocationManager;
- private final PendingIntent mPendingIntent;
- private final LinkedBlockingQueue<Location> mLocations;
- private final LinkedBlockingQueue<Boolean> mProviderChanges;
-
- public LocationPendingIntentCapture(Context context) {
- mContext = context;
- mLocationManager = context.getSystemService(LocationManager.class);
- mPendingIntent = PendingIntent.getBroadcast(context, sRequestCode.getAndIncrement(),
- new Intent(ACTION).setPackage(context.getPackageName()),
- PendingIntent.FLAG_CANCEL_CURRENT);
- mLocations = new LinkedBlockingQueue<>();
- mProviderChanges = new LinkedBlockingQueue<>();
-
- context.registerReceiver(this, new IntentFilter(ACTION));
- }
-
- public PendingIntent getPendingIntent() {
- return mPendingIntent;
- }
-
- /**
- * May not be called from the main thread. Tests do not run on the main thread so this
- * generally shouldn't be a problem.
- */
- public Location getNextLocation(long timeoutMs) throws InterruptedException {
- Preconditions.checkState(Looper.myLooper() != Looper.getMainLooper());
- return mLocations.poll(timeoutMs, TimeUnit.MILLISECONDS);
- }
-
- /**
- * May not be called from the main thread. Tests do not run on the main thread so this
- * generally shouldn't be a problem.
- */
- public Boolean getNextProviderChange(long timeoutMs) throws InterruptedException {
- Preconditions.checkState(Looper.myLooper() != Looper.getMainLooper());
- return mProviderChanges.poll(timeoutMs, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public void close() {
- mLocationManager.removeUpdates(mPendingIntent);
- mContext.unregisterReceiver(this);
- mPendingIntent.cancel();
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.hasExtra(KEY_PROVIDER_ENABLED)) {
- mProviderChanges.add(intent.getBooleanExtra(KEY_PROVIDER_ENABLED, false));
- } else if (intent.hasExtra(KEY_LOCATION_CHANGED)) {
- mLocations.add(intent.getParcelableExtra(KEY_LOCATION_CHANGED));
+ // it's ok if this times out, as we don't notify for noop changes
+ if (!latch.await(500, TimeUnit.MILLISECONDS)) {
+ Log.i(TAG, "timeout while waiting for provider enabled change");
}
- }
- }
-
- private static class ProximityPendingIntentCapture extends BroadcastReceiver implements
- AutoCloseable {
-
- private static final String ACTION = "android.location.cts.LOCATION_BROADCAST";
- private static final AtomicInteger sRequestCode = new AtomicInteger(0);
-
- private final Context mContext;
- private final LocationManager mLocationManager;
- private final PendingIntent mPendingIntent;
- private final LinkedBlockingQueue<Boolean> mProximityChanges;
-
- public ProximityPendingIntentCapture(Context context) {
- mContext = context;
- mLocationManager = context.getSystemService(LocationManager.class);
- mPendingIntent = PendingIntent.getBroadcast(context, sRequestCode.getAndIncrement(),
- new Intent(ACTION).setPackage(context.getPackageName()),
- PendingIntent.FLAG_CANCEL_CURRENT);
- mProximityChanges = new LinkedBlockingQueue<>();
-
- context.registerReceiver(this, new IntentFilter(ACTION));
- }
-
- public PendingIntent getPendingIntent() {
- return mPendingIntent;
- }
-
- /**
- * May not be called from the main thread. Tests do not run on the main thread so this
- * generally shouldn't be a problem.
- */
- public Boolean getNextProximityChange(long timeoutMs) throws InterruptedException {
- Preconditions.checkState(Looper.myLooper() != Looper.getMainLooper());
- return mProximityChanges.poll(timeoutMs, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public void close() {
- mLocationManager.removeProximityAlert(mPendingIntent);
- mContext.unregisterReceiver(this);
- mPendingIntent.cancel();
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.hasExtra(KEY_PROXIMITY_ENTERING)) {
- mProximityChanges.add(intent.getBooleanExtra(KEY_PROXIMITY_ENTERING, false));
- }
- }
- }
-
- private static class GetCurrentLocationCapture implements Consumer<Location>, AutoCloseable {
-
- private final CancellationSignal mCancellationSignal;
- private final LinkedBlockingQueue<Location> locations;
-
- public GetCurrentLocationCapture() {
- locations = new LinkedBlockingQueue<>();
- mCancellationSignal = new CancellationSignal();
- }
-
- public CancellationSignal getCancellationSignal() {
- return mCancellationSignal;
- }
-
- public Location getNextLocation(long timeoutMs) throws InterruptedException {
- return locations.poll(timeoutMs, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public void accept(Location location) {
- locations.add(location);
- }
-
- @Override
- public void close() {
- mCancellationSignal.cancel();
+ mContext.unregisterReceiver(receiver);
+ } else {
+ mManager.setTestProviderEnabled(provider, enabled);
}
}
}
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationTest.java
index 270148c..4c1d586 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationTest.java
@@ -16,15 +16,27 @@
package android.location.cts.fine;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import android.location.Location;
import android.os.Bundle;
import android.os.Parcel;
-import android.test.AndroidTestCase;
import android.util.StringBuilderPrinter;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.text.DecimalFormat;
-public class LocationTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class LocationTest {
private static final float DELTA = 0.1f;
private final float TEST_ACCURACY = 1.0f;
@@ -43,10 +55,7 @@
private final boolean TEST_KEY1VALUE = false;
private final byte TEST_KEY2VALUE = 10;
- private static final String ENABLED_KEY = "enabled";
- private static final String MESSENGER_KEY = "messenger";
-
-
+ @Test
public void testConstructor() {
new Location("LocationProvider");
@@ -62,6 +71,7 @@
}
}
+ @Test
public void testDump() {
StringBuilder sb = new StringBuilder();
StringBuilderPrinter printer = new StringBuilderPrinter(sb);
@@ -70,6 +80,7 @@
assertNotNull(sb.toString());
}
+ @Test
public void testBearingTo() {
Location location = new Location("");
Location dest = new Location("");
@@ -110,6 +121,7 @@
}
}
+ @Test
public void testConvert_CoordinateToRepresentation() {
DecimalFormat df = new DecimalFormat("###.#####");
String result;
@@ -154,20 +166,21 @@
}
}
+ @Test
public void testConvert_RepresentationToCoordinate() {
double result;
result = Location.convert("-80.075");
- assertEquals(-80.075, result);
+ assertEquals(-80.075, result, DELTA);
result = Location.convert("-80:05.10000");
- assertEquals(-80.085, result);
+ assertEquals(-80.085, result, DELTA);
result = Location.convert("-80:04:03.00000");
- assertEquals(-80.0675, result);
+ assertEquals(-80.0675, result, DELTA);
result = Location.convert("-80:4:3");
- assertEquals(-80.0675, result);
+ assertEquals(-80.0675, result, DELTA);
try {
Location.convert(null);
@@ -205,11 +218,13 @@
}
}
+ @Test
public void testDescribeContents() {
Location location = new Location("");
location.describeContents();
}
+ @Test
public void testDistanceBetween() {
float[] result = new float[3];
Location.distanceBetween(0, 0, 0, 0, result);
@@ -237,6 +252,7 @@
}
}
+ @Test
public void testDistanceTo() {
float distance;
Location zeroLocation = new Location("");
@@ -254,6 +270,7 @@
assertEquals(6244139.0, distance, 1);
}
+ @Test
public void testAccessAccuracy() {
Location location = new Location("");
assertFalse(location.hasAccuracy());
@@ -263,6 +280,7 @@
assertTrue(location.hasAccuracy());
}
+ @Test
public void testAccessVerticalAccuracy() {
Location location = new Location("");
assertFalse(location.hasVerticalAccuracy());
@@ -272,6 +290,7 @@
assertTrue(location.hasVerticalAccuracy());
}
+ @Test
public void testAccessSpeedAccuracy() {
Location location = new Location("");
assertFalse(location.hasSpeedAccuracy());
@@ -281,6 +300,7 @@
assertTrue(location.hasSpeedAccuracy());
}
+ @Test
public void testAccessBearingAccuracy() {
Location location = new Location("");
assertFalse(location.hasBearingAccuracy());
@@ -291,6 +311,7 @@
}
+ @Test
public void testAccessAltitude() {
Location location = new Location("");
assertFalse(location.hasAltitude());
@@ -300,6 +321,7 @@
assertTrue(location.hasAltitude());
}
+ @Test
public void testAccessBearing() {
Location location = new Location("");
assertFalse(location.hasBearing());
@@ -317,6 +339,7 @@
assertTrue(location.hasBearing());
}
+ @Test
public void testAccessExtras() {
Location location = createTestLocation();
@@ -326,6 +349,7 @@
assertNull(location.getExtras());
}
+ @Test
public void testAccessLatitude() {
Location location = new Location("");
@@ -339,6 +363,7 @@
assertEquals(-90, location.getLatitude(), DELTA);
}
+ @Test
public void testAccessLongitude() {
Location location = new Location("");
@@ -352,6 +377,7 @@
assertEquals(-180, location.getLongitude(), DELTA);
}
+ @Test
public void testAccessProvider() {
Location location = new Location("");
@@ -363,6 +389,7 @@
assertNull(location.getProvider());
}
+ @Test
public void testAccessSpeed() {
Location location = new Location("");
assertFalse(location.hasSpeed());
@@ -385,6 +412,7 @@
assertEquals(12000, location.getTime());
}
+ @Test
public void testAccessElapsedRealtime() {
Location location = new Location("");
@@ -398,20 +426,22 @@
assertEquals(12000, location.getElapsedRealtimeNanos());
}
+ @Test
public void testAccessElapsedRealtimeUncertaintyNanos() {
Location location = new Location("");
assertFalse(location.hasElapsedRealtimeUncertaintyNanos());
- assertEquals(0.0, location.getElapsedRealtimeUncertaintyNanos());
+ assertEquals(0.0, location.getElapsedRealtimeUncertaintyNanos(), DELTA);
location.setElapsedRealtimeUncertaintyNanos(12000.0);
- assertEquals(12000.0, location.getElapsedRealtimeUncertaintyNanos());
+ assertEquals(12000.0, location.getElapsedRealtimeUncertaintyNanos(), DELTA);
assertTrue(location.hasElapsedRealtimeUncertaintyNanos());
location.reset();
assertFalse(location.hasElapsedRealtimeUncertaintyNanos());
- assertEquals(0.0, location.getElapsedRealtimeUncertaintyNanos());
+ assertEquals(0.0, location.getElapsedRealtimeUncertaintyNanos(), DELTA);
}
+ @Test
public void testSet() {
Location location = new Location("");
@@ -445,12 +475,14 @@
assertNull(location.getExtras());
}
+ @Test
public void testToString() {
Location location = createTestLocation();
assertNotNull(location.toString());
}
+ @Test
public void testWriteToParcel() {
Location location = createTestLocation();
diff --git a/tests/location/common/src/android/location/cts/common/GnssTestCase.java b/tests/location/location_gnss/src/android/location/cts/common/GnssTestCase.java
similarity index 80%
rename from tests/location/common/src/android/location/cts/common/GnssTestCase.java
rename to tests/location/location_gnss/src/android/location/cts/common/GnssTestCase.java
index 10aeaad..03f824e 100644
--- a/tests/location/common/src/android/location/cts/common/GnssTestCase.java
+++ b/tests/location/location_gnss/src/android/location/cts/common/GnssTestCase.java
@@ -19,12 +19,12 @@
/**
* Base Test Case class for all Gnss Tests.
+ *
+ * @deprecated Pointless base class, do not use.
*/
+@Deprecated
public abstract class GnssTestCase extends AndroidTestCase {
- // This is used to mark cts tests as CtsVerifier tests.
- private volatile boolean mCtsVerifierTest = false;
-
protected static boolean YEAR_2017_CAPABILITY_ENFORCED = false;
public TestLocationManager mTestLocationManager;
@@ -32,11 +32,7 @@
protected GnssTestCase() {
}
- public void setTestAsCtsVerifierTest(boolean value) {
- mCtsVerifierTest = value;
- }
-
public boolean isCtsVerifierTest() {
- return mCtsVerifierTest;
+ return false;
}
}
diff --git a/tests/location/common/src/android/location/cts/common/SoftAssert.java b/tests/location/location_gnss/src/android/location/cts/common/SoftAssert.java
similarity index 100%
rename from tests/location/common/src/android/location/cts/common/SoftAssert.java
rename to tests/location/location_gnss/src/android/location/cts/common/SoftAssert.java
diff --git a/tests/location/common/src/android/location/cts/common/TestLocationManager.java b/tests/location/location_gnss/src/android/location/cts/common/TestLocationManager.java
similarity index 100%
rename from tests/location/common/src/android/location/cts/common/TestLocationManager.java
rename to tests/location/location_gnss/src/android/location/cts/common/TestLocationManager.java
diff --git a/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java b/tests/location/location_gnss/src/android/location/cts/common/TestMeasurementUtil.java
similarity index 100%
rename from tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
rename to tests/location/location_gnss/src/android/location/cts/common/TestMeasurementUtil.java
diff --git a/tests/location/common/src/android/location/cts/common/TestUtils.java b/tests/location/location_gnss/src/android/location/cts/common/TestUtils.java
similarity index 100%
rename from tests/location/common/src/android/location/cts/common/TestUtils.java
rename to tests/location/location_gnss/src/android/location/cts/common/TestUtils.java
diff --git a/tests/sensor/AndroidTest.xml b/tests/sensor/AndroidTest.xml
index 8edee41..69335d1 100644
--- a/tests/sensor/AndroidTest.xml
+++ b/tests/sensor/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="config-descriptor:metadata" key="component" value="location" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
index d0756b9..bbf942e 100644
--- a/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="config-descriptor:metadata" key="component" value="systems" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsAndroidTestBaseCurrentApiSignatureTestCases.apk" />
diff --git a/tests/tests/assist/AndroidTest.xml b/tests/tests/assist/AndroidTest.xml
index c8014e6..6f34e08 100644
--- a/tests/tests/assist/AndroidTest.xml
+++ b/tests/tests/assist/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<!-- Force service to be installed as non-instant mode, always -->
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/batterysaving/src/android/os/cts/powerwhitelist/PowerWhitelistTest.java b/tests/tests/batterysaving/src/android/os/cts/powerwhitelist/PowerWhitelistTest.java
new file mode 100644
index 0000000..b1fb840
--- /dev/null
+++ b/tests/tests/batterysaving/src/android/os/cts/powerwhitelist/PowerWhitelistTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 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.os.cts.powerwhitelist;
+
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PowerWhitelistTest {
+ @Test
+ public void testPowerWhitelistManager() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ assertNotNull(context.getSystemService(Context.POWER_WHITELIST_MANAGER));
+ }
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp b/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
index f0e4006..ad6a1c9 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
@@ -32,6 +32,9 @@
java: {
sdk_version: "28",
},
+ cpp: {
+ enabled: false,
+ }
},
}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ITest.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ITest.aidl
index 6c62157..72d5985 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ITest.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ITest.aidl
@@ -41,6 +41,8 @@
String[] RepeatStringArray(in String[] input, out String[] repeated);
test_package.RegularPolygon[] RepeatRegularPolygonArray(in test_package.RegularPolygon[] input, out test_package.RegularPolygon[] repeated);
ParcelFileDescriptor[] RepeatFdArray(in ParcelFileDescriptor[] input, out ParcelFileDescriptor[] repeated);
+ List<String> Repeat2StringList(in List<String> input, out List<String> repeated);
+ List<test_package.RegularPolygon> Repeat2RegularPolygonList(in List<test_package.RegularPolygon> input, out List<test_package.RegularPolygon> repeated);
@nullable boolean[] RepeatNullableBooleanArray(in @nullable boolean[] input);
@nullable byte[] RepeatNullableByteArray(in @nullable byte[] input);
@nullable char[] RepeatNullableCharArray(in @nullable char[] input);
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/2/test_package/ITest.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/2/test_package/ITest.aidl
index b11361d..891cf0b 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/2/test_package/ITest.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/2/test_package/ITest.aidl
@@ -41,6 +41,8 @@
String[] RepeatStringArray(in String[] input, out String[] repeated);
test_package.RegularPolygon[] RepeatRegularPolygonArray(in test_package.RegularPolygon[] input, out test_package.RegularPolygon[] repeated);
ParcelFileDescriptor[] RepeatFdArray(in ParcelFileDescriptor[] input, out ParcelFileDescriptor[] repeated);
+ List<String> Repeat2StringList(in List<String> input, out List<String> repeated);
+ List<test_package.RegularPolygon> Repeat2RegularPolygonList(in List<test_package.RegularPolygon> input, out List<test_package.RegularPolygon> repeated);
@nullable boolean[] RepeatNullableBooleanArray(in @nullable boolean[] input);
@nullable byte[] RepeatNullableByteArray(in @nullable byte[] input);
@nullable char[] RepeatNullableCharArray(in @nullable char[] input);
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/itest_impl.h b/tests/tests/binder_ndk/libbinder_ndk_test/itest_impl.h
index d4cbd22..812eb04 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/itest_impl.h
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/itest_impl.h
@@ -298,6 +298,37 @@
*_aidl_return = in_value;
return ::ndk::ScopedAStatus(AStatus_newOk());
}
+
+ ::ndk::ScopedAStatus Repeat2StringList(const std::vector<std::string>& in_input,
+ std::vector<std::string>* out_repeated,
+ std::vector<std::string>* _aidl_return) override {
+ *out_repeated = std::vector<std::string>();
+ *_aidl_return = std::vector<std::string>();
+ for (int i = 0; i < 2; i++) {
+ for (auto& s : in_input) {
+ out_repeated->emplace_back(s);
+ _aidl_return->emplace_back(s);
+ }
+ }
+
+ return ::ndk::ScopedAStatus(AStatus_newOk());
+ }
+
+ ::ndk::ScopedAStatus Repeat2RegularPolygonList(
+ const std::vector<::aidl::test_package::RegularPolygon>& in_input,
+ std::vector<::aidl::test_package::RegularPolygon>* out_repeated,
+ std::vector<::aidl::test_package::RegularPolygon>* _aidl_return) override {
+ *out_repeated = std::vector<::aidl::test_package::RegularPolygon>();
+ *_aidl_return = std::vector<::aidl::test_package::RegularPolygon>();
+ for (int i = 0; i < 2; i++) {
+ for (auto& s : in_input) {
+ out_repeated->emplace_back(s);
+ _aidl_return->emplace_back(s);
+ }
+ }
+ return ::ndk::ScopedAStatus(AStatus_newOk());
+ }
+
::ndk::ScopedAStatus RepeatNullableBooleanArray(
const std::optional<std::vector<bool>>& in_value,
std::optional<std::vector<bool>>* _aidl_return) override {
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
index cc9737c..d15ec1d 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
@@ -504,6 +504,23 @@
}
}
+template <typename T>
+void testRepeat2List(const std::shared_ptr<ITest>& i, RepeatMethod<T> repeatMethod,
+ std::vector<std::vector<T>> tests) {
+ for (const auto& input : tests) {
+ std::vector<T> out1;
+ std::vector<T> out2;
+ std::vector<T> expected;
+
+ expected.insert(expected.end(), input.begin(), input.end());
+ expected.insert(expected.end(), input.begin(), input.end());
+
+ ASSERT_OK((i.get()->*repeatMethod)(input, &out1, &out2)) << expected.size();
+ EXPECT_EQ(expected, out1);
+ EXPECT_EQ(expected, out2);
+ }
+}
+
TEST_P(NdkBinderTest_Aidl, Arrays) {
testRepeat<bool>(iface, &ITest::RepeatBooleanArray,
{
@@ -579,6 +596,22 @@
});
}
+TEST_P(NdkBinderTest_Aidl, Lists) {
+ testRepeat2List<std::string>(iface, &ITest::Repeat2StringList,
+ {
+ {},
+ {"asdf"},
+ {"", "aoeu", "lol", "brb"},
+ });
+ testRepeat2List<RegularPolygon>(
+ iface, &ITest::Repeat2RegularPolygonList,
+ {
+ {},
+ {{"hexagon", 6, 2.0f}},
+ {{"hexagon", 6, 2.0f}, {"square", 4, 7.0f}, {"pentagon", 5, 4.2f}},
+ });
+}
+
template <typename T>
using RepeatNullableMethod = ScopedAStatus (ITest::*)(
const std::optional<std::vector<std::optional<T>>>&,
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/test_package/ITest.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/test_package/ITest.aidl
index df4eb42..669f683 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/test_package/ITest.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/test_package/ITest.aidl
@@ -90,6 +90,10 @@
RegularPolygon[] RepeatRegularPolygonArray(in RegularPolygon[] input, out RegularPolygon[] repeated);
ParcelFileDescriptor[] RepeatFdArray(in ParcelFileDescriptor[] input, out ParcelFileDescriptor[] repeated);
+ // Lists
+ List<String> Repeat2StringList(in List<String> input, out List<String> repeated);
+ List<RegularPolygon> Repeat2RegularPolygonList(in List<RegularPolygon> input, out List<RegularPolygon> repeated);
+
// Nullable Arrays
@nullable boolean[] RepeatNullableBooleanArray(in @nullable boolean[] input);
@nullable byte[] RepeatNullableByteArray(in @nullable byte[] input);
diff --git a/tests/tests/binder_ndk/src/android/binder/cts/JavaClientTest.java b/tests/tests/binder_ndk/src/android/binder/cts/JavaClientTest.java
index 35b9953..01429f6 100644
--- a/tests/tests/binder_ndk/src/android/binder/cts/JavaClientTest.java
+++ b/tests/tests/binder_ndk/src/android/binder/cts/JavaClientTest.java
@@ -49,6 +49,9 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.function.BiPredicate;
@RunWith(Parameterized.class)
public class JavaClientTest {
@@ -412,6 +415,41 @@
}
@Test
+ public void testLists() throws RemoteException {
+ {
+ List<String> value = Arrays.asList("", "aoeu", "lol", "brb");
+ List<String> out1 = new ArrayList<>();
+ List<String> out2 = mInterface.Repeat2StringList(value, out1);
+
+ List<String> expected = new ArrayList<>();
+ expected.addAll(value);
+ expected.addAll(value);
+ String[] expectedArray = expected.toArray(new String[0]);
+
+ Assert.assertArrayEquals(expectedArray, out1.toArray(new String[0]));
+ Assert.assertArrayEquals(expectedArray, out2.toArray(new String[0]));
+ }
+ {
+ RegularPolygon septagon = new RegularPolygon();
+ septagon.name = "septagon";
+ septagon.numSides = 7;
+ septagon.sideLength = 1.0f;
+
+ List<RegularPolygon> value = Arrays.asList(septagon, new RegularPolygon(), new RegularPolygon());
+ List<RegularPolygon> out1 = new ArrayList<>();
+ List<RegularPolygon> out2 = mInterface.Repeat2RegularPolygonList(value, out1);
+
+ List<RegularPolygon> expected = new ArrayList<>();
+ expected.addAll(value);
+ expected.addAll(value);
+ RegularPolygon[] expectedArray = expected.toArray(new RegularPolygon[0]);
+
+ assertPolygonEquals(expectedArray, out1.toArray(new RegularPolygon[0]));
+ assertPolygonEquals(expectedArray, out1.toArray(new RegularPolygon[0]));
+ }
+ }
+
+ @Test
public void testNullableArrays() throws RemoteException {
{
boolean[] emptyValue = {};
diff --git a/tests/tests/binder_ndk/src/android/binder/cts/TestImpl.java b/tests/tests/binder_ndk/src/android/binder/cts/TestImpl.java
index 6defe56..828d11e 100644
--- a/tests/tests/binder_ndk/src/android/binder/cts/TestImpl.java
+++ b/tests/tests/binder_ndk/src/android/binder/cts/TestImpl.java
@@ -284,6 +284,19 @@
return out;
}
+ public java.util.List<String> Repeat2StringList(java.util.List<String> in_value, java.util.List<String> repeated) {
+ repeated.addAll(in_value);
+ repeated.addAll(in_value);
+ return repeated;
+ }
+
+ @Override
+ public java.util.List<RegularPolygon> Repeat2RegularPolygonList(java.util.List<RegularPolygon> in_value, java.util.List<RegularPolygon> repeated) {
+ repeated.addAll(in_value);
+ repeated.addAll(in_value);
+ return repeated;
+ }
+
@Override
public boolean[] RepeatNullableBooleanArray(boolean[] in_value) {
return in_value;
diff --git a/tests/tests/car/OWNERS b/tests/tests/car/OWNERS
index ce0e81b..cdff026 100644
--- a/tests/tests/car/OWNERS
+++ b/tests/tests/car/OWNERS
@@ -1,2 +1,6 @@
# Bug component: 526266
+felipeal@google.com
+gurunagarajan@google.com
+keunyoung@google.com
nicksauer@google.com
+sgurun@google.com
diff --git a/tests/tests/car/src/android/car/cts/CarOccupantZoneManagerTest.java b/tests/tests/car/src/android/car/cts/CarOccupantZoneManagerTest.java
new file mode 100644
index 0000000..b7ef096
--- /dev/null
+++ b/tests/tests/car/src/android/car/cts/CarOccupantZoneManagerTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 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.car.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static java.util.stream.Collectors.toList;
+
+import android.car.Car;
+import android.car.CarOccupantZoneManager;
+import android.car.CarOccupantZoneManager.OccupantZoneInfo;
+import android.os.Process;
+import android.os.UserHandle;
+import android.platform.test.annotations.RequiresDevice;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.Display;
+
+import java.util.List;
+
+@SmallTest
+@RequiresDevice
+public class CarOccupantZoneManagerTest extends CarApiTestBase {
+
+ private OccupantZoneInfo mDriverZoneInfo;
+
+ private CarOccupantZoneManager mCarOccupantZoneManager;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ mCarOccupantZoneManager =
+ (CarOccupantZoneManager) getCar().getCarManager(Car.CAR_OCCUPANT_ZONE_SERVICE);
+
+ // Retrieve the current driver zone info (disregarding the driver's seat - LHD or RHD).
+ // Ensures there is only one driver zone info.
+ List<OccupantZoneInfo> drivers =
+ mCarOccupantZoneManager.getAllOccupantZones().stream().filter(
+ o -> o.occupantType == CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER).collect(
+ toList());
+ assertWithMessage("One and only one driver zone info is expected per config")
+ .that(drivers).hasSize(1);
+ mDriverZoneInfo = drivers.get(0);
+ }
+
+ public void testDriverUserIdMustBeCurrentUser() {
+ int myUid = Process.myUid();
+ assertWithMessage("Driver user id must correspond to current user id (Process.myUid: %d)",
+ myUid).that(
+ UserHandle.getUserId(myUid)).isEqualTo(
+ mCarOccupantZoneManager.getUserForOccupant(mDriverZoneInfo));
+ }
+
+ public void testExpectAtLeastDriverZoneExists() {
+ assertWithMessage(
+ "Driver zone is expected to exist. Make sure a driver zone is properly defined in"
+ + " config.xml/config_occupant_display_mapping")
+ .that(mCarOccupantZoneManager.getAllOccupantZones())
+ .contains(mDriverZoneInfo);
+ }
+
+ public void testDriverHasMainDisplay() {
+ assertWithMessage("Driver is expected to be associated with main display")
+ .that(mCarOccupantZoneManager.getAllDisplaysForOccupant(mDriverZoneInfo))
+ .contains(getDriverDisplay());
+ }
+
+ public void testDriverDisplayIdIsDefaultDisplay() {
+ assertThat(getDriverDisplay().getDisplayId()).isEqualTo(Display.DEFAULT_DISPLAY);
+ }
+
+ private Display getDriverDisplay() {
+ Display driverDisplay =
+ mCarOccupantZoneManager.getDisplayForOccupant(
+ mDriverZoneInfo, CarOccupantZoneManager.DISPLAY_TYPE_MAIN);
+ assertWithMessage(
+ "No display set for driver. Make sure a default display is set in"
+ + " config.xml/config_occupant_display_mapping")
+ .that(driverDisplay)
+ .isNotNull();
+ return driverDisplay;
+ }
+}
+
diff --git a/tests/tests/deviceconfig/AndroidTest.xml b/tests/tests/deviceconfig/AndroidTest.xml
index d4a6a21..0d3a8b8 100644
--- a/tests/tests/deviceconfig/AndroidTest.xml
+++ b/tests/tests/deviceconfig/AndroidTest.xml
@@ -19,6 +19,7 @@
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsDeviceConfigTestCases.apk" />
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index e1e868c..317acc0 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -1967,6 +1967,7 @@
if (resId == R.drawable.webp_orientation1) {
// The webp files may not look exactly the same as the jpegs.
// Recreate the reference.
+ reference.recycle();
reference = null;
isWebp = true;
}
@@ -1986,6 +1987,7 @@
} else {
int mse = isWebp ? 70 : 1;
BitmapUtils.assertBitmapsMse(bm, reference, mse, true, false);
+ bm.recycle();
}
} catch (IOException e) {
fail("Decoding " + uri.toString() + " yielded " + e);
diff --git a/tests/tests/media/src/android/media/cts/AudioEffectTest.java b/tests/tests/media/src/android/media/cts/AudioEffectTest.java
index ae8458c..71da50b 100644
--- a/tests/tests/media/src/android/media/cts/AudioEffectTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioEffectTest.java
@@ -37,6 +37,7 @@
import java.util.UUID;
@AppModeFull(reason = "Dynamic congic not supported")
+@NonMediaMainlineTest
public class AudioEffectTest extends PostProcTestBase {
private String TAG = "AudioEffectTest";
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
index a4ba637..8e15543 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
@@ -46,6 +46,7 @@
* Executes a range of tests on MediaPlayer while streaming a video
* from an HTTP server over a simulated "flaky" network.
*/
+@NonMediaMainlineTest
@AppModeFull(reason = "TODO: evaluate and port to instant")
public class MediaPlayerFlakyNetworkTest extends MediaPlayerTestBase {
private static final String PKG = "android.media.cts";
diff --git a/tests/tests/media/src/android/media/cts/MediaRandomTest.java b/tests/tests/media/src/android/media/cts/MediaRandomTest.java
index 306b451..30fd364 100644
--- a/tests/tests/media/src/android/media/cts/MediaRandomTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRandomTest.java
@@ -38,6 +38,7 @@
* Blender Foundation / www.bigbuckbunny.org, and are licensed under the Creative Commons
* Attribution 3.0 License at http://creativecommons.org/licenses/by/3.0/us/.
*/
+@NonMediaMainlineTest
@MediaHeavyPresubmitTest
@AppModeFull(reason = "TODO: evaluate and port to instant")
public class MediaRandomTest extends ActivityInstrumentationTestCase2<MediaStubActivity> {
diff --git a/tests/tests/media/src/android/media/cts/RoutingTest.java b/tests/tests/media/src/android/media/cts/RoutingTest.java
index e7d562c..f6b3c20 100644
--- a/tests/tests/media/src/android/media/cts/RoutingTest.java
+++ b/tests/tests/media/src/android/media/cts/RoutingTest.java
@@ -567,11 +567,20 @@
}
private MediaPlayer allocMediaPlayer() {
+ return allocMediaPlayer(null, true);
+ }
+
+ private MediaPlayer allocMediaPlayer(AudioDeviceInfo device, boolean start) {
final int resid = R.raw.testmp3_2;
MediaPlayer mediaPlayer = MediaPlayer.create(mContext, resid);
mediaPlayer.setAudioAttributes(
new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build());
- mediaPlayer.start();
+ if (device != null) {
+ mediaPlayer.setPreferredDevice(device);
+ }
+ if (start) {
+ mediaPlayer.start();
+ }
return mediaPlayer;
}
@@ -753,15 +762,19 @@
MediaPlayer mediaPlayer = null;
try {
- mediaPlayer = allocMediaPlayer();
-
- mediaPlayer.setPreferredDevice(telephonyDevice);
+ mediaPlayer = allocMediaPlayer(telephonyDevice, false);
assertEquals(AudioDeviceInfo.TYPE_TELEPHONY, mediaPlayer.getPreferredDevice().getType());
-
- // Sleep for 1s to ensure the output device open
+ mediaPlayer.start();
+ // Sleep for 1s to ensure the underlying AudioTrack is created and started
SystemClock.sleep(1000);
- assertTrue(mediaPlayer.getRoutedDevice().getType() != AudioDeviceInfo.TYPE_TELEPHONY);
-
+ telephonyDevice = mediaPlayer.getRoutedDevice();
+ // 3 behaviors are accepted when permission to play to telephony device is rejected:
+ // - indicate a null routed device
+ // - fallback to another device for playback
+ // - stop playback in error.
+ assertTrue(telephonyDevice == null
+ || telephonyDevice.getType() != AudioDeviceInfo.TYPE_TELEPHONY
+ || !mediaPlayer.isPlaying());
} finally {
if (mediaPlayer != null) {
mediaPlayer.stop();
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index ede1711..e215ee6 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -48,6 +48,7 @@
/**
* Tests of MediaPlayer streaming capabilities.
*/
+@NonMediaMainlineTest
@AppModeFull(reason = "TODO: evaluate and port to instant")
public class StreamingMediaPlayerTest extends MediaPlayerTestBase {
diff --git a/tests/tests/media/src/android/media/cts/VideoCodecTest.java b/tests/tests/media/src/android/media/cts/VideoCodecTest.java
index 8aec3cc..7439aa1 100644
--- a/tests/tests/media/src/android/media/cts/VideoCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoCodecTest.java
@@ -25,6 +25,7 @@
import android.media.cts.R;
import java.io.File;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@@ -98,7 +99,8 @@
bitRateMode,
targetBitrate,
true);
- ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+ ArrayList<ByteBuffer> codecConfigs = new ArrayList<>();
+ ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params, codecConfigs);
if (bufInfo == null) {
continue;
}
@@ -116,7 +118,8 @@
MAX_BITRATE_VARIATION * targetBitrate);
}
- decode(params.outputIvfFilename, null, codecMimeType, FPS, params.forceGoogleEncoder);
+ decode(params.outputIvfFilename, null, codecMimeType, FPS,
+ params.forceGoogleEncoder, codecConfigs);
}
if (skipped) {
@@ -147,13 +150,15 @@
bitRateMode,
BITRATE,
syncEncoding);
- ArrayList<MediaCodec.BufferInfo> bufInfos = encodeAsync(params);
+ ArrayList<ByteBuffer> codecConfigs = new ArrayList<>();
+ ArrayList<MediaCodec.BufferInfo> bufInfos = encodeAsync(params, codecConfigs);
if (bufInfos == null) {
Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
return;
}
computeEncodingStatistics(bufInfos);
- decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+ decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS,
+ params.forceGoogleEncoder, codecConfigs);
VideoDecodingStatistics statisticsAsync = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -172,13 +177,15 @@
bitRateMode,
BITRATE,
syncEncoding);
- bufInfos = encode(params);
+ codecConfigs.clear();
+ bufInfos = encode(params, codecConfigs);
if (bufInfos == null) {
Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
return;
}
computeEncodingStatistics(bufInfos);
- decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+ decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS,
+ params.forceGoogleEncoder, codecConfigs);
VideoDecodingStatistics statisticsSync = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -351,11 +358,17 @@
BITRATE,
true);
final String inputIvfFilename = params.outputIvfFilename;
+ final ArrayList<ByteBuffer> codecConfigs = new ArrayList<>();
Runnable runEncoder = new Runnable() {
public void run() {
try {
- ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+ ArrayList<MediaCodec.BufferInfo> bufInfo;
+ if (codecConfigs.isEmpty()) {
+ bufInfo = encode(params, codecConfigs);
+ } else {
+ bufInfo = encode(params);
+ }
VideoEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
bitrate[0] = statistics.mAverageBitrate;
} catch (Exception e) {
@@ -367,7 +380,8 @@
Runnable runDecoder = new Runnable() {
public void run() {
try {
- decode(inputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+ decode(inputIvfFilename, OUTPUT_YUV, codecMimeType, FPS,
+ params.forceGoogleEncoder, codecConfigs);
VideoDecodingStatistics statistics = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -448,7 +462,8 @@
bitRateMode,
TEST_BITRATES_SET[i],
true);
- if (encode(params) == null) {
+ ArrayList<ByteBuffer> codecConfigs = new ArrayList<>();
+ if (encode(params, codecConfigs) == null) {
// parameters not supported, try other bitrates
completed[i] = false;
continue;
@@ -456,7 +471,8 @@
completed[i] = true;
skipped = false;
- decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+ decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS,
+ params.forceGoogleEncoder, codecConfigs);
VideoDecodingStatistics statistics = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
diff --git a/tests/tests/media/src/android/media/cts/VideoCodecTestBase.java b/tests/tests/media/src/android/media/cts/VideoCodecTestBase.java
index 7dd1018..82c8b18 100644
--- a/tests/tests/media/src/android/media/cts/VideoCodecTestBase.java
+++ b/tests/tests/media/src/android/media/cts/VideoCodecTestBase.java
@@ -39,8 +39,8 @@
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
-import java.util.Locale;
import java.util.ArrayList;
+import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@@ -532,13 +532,15 @@
* @param outputYuvFilename The name of the output YUV file (optional).
* @param frameRate Frame rate of input file in frames per second
* @param forceGoogleDecoder Force to use Google Video decoder.
+ * @param codecConfigs Codec config buffers to be added to the format
*/
protected ArrayList<MediaCodec.BufferInfo> decode(
String inputIvfFilename,
String outputYuvFilename,
String codecMimeType,
int frameRate,
- boolean forceGoogleDecoder) throws Exception {
+ boolean forceGoogleDecoder,
+ ArrayList<ByteBuffer> codecConfigs) throws Exception {
ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
// Open input/output.
@@ -567,6 +569,11 @@
}
int frameColorFormat = properties.colorFormat;
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+ int csdIndex = 0;
+ for (ByteBuffer config : codecConfigs) {
+ format.setByteBuffer("csd-" + csdIndex, config);
+ ++csdIndex;
+ }
FileOutputStream yuv = null;
if (outputYuvFilename != null) {
@@ -761,6 +768,7 @@
private final CodecProperties mProperties;
private final ArrayList<MediaCodec.BufferInfo> mBufferInfos;
private final IvfWriter mIvf;
+ private final ArrayList<ByteBuffer> mCodecConfigs;
private final byte[] mSrcFrame;
private InputStream mYuvStream;
@@ -770,12 +778,14 @@
EncoderOutputStreamParameters streamParams,
CodecProperties properties,
ArrayList<MediaCodec.BufferInfo> bufferInfos,
- IvfWriter ivf)
+ IvfWriter ivf,
+ ArrayList<ByteBuffer> codecConfigs)
throws Exception {
mStreamParams = streamParams;
mProperties = properties;
mBufferInfos = bufferInfos;
mIvf = ivf;
+ mCodecConfigs = codecConfigs;
int srcFrameSize = streamParams.frameWidth * streamParams.frameHeight * 3 / 2;
mSrcFrame = new byte[srcFrameSize];
@@ -820,6 +830,12 @@
public boolean saveOutputFrame(MediaEncoderOutput out) {
if (out.outputGenerated) {
+ if ((out.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
+ Log.d(TAG, "Storing codec config separately");
+ mCodecConfigs.add(
+ ByteBuffer.allocate(out.buffer.length).put(out.buffer));
+ out.buffer = new byte[0];
+ }
if (out.buffer.length > 0) {
// Save frame
try {
@@ -1306,6 +1322,14 @@
}
/**
+ * @see #encode(EncoderOutputStreamParameters, ArrayList<ByteBuffer>)
+ */
+ protected ArrayList<MediaCodec.BufferInfo> encode(
+ EncoderOutputStreamParameters streamParams) throws Exception {
+ return encode(streamParams, new ArrayList<ByteBuffer>());
+ }
+
+ /**
* Video encoding loop supporting encoding single streams with an option
* to run in a looper thread and use buffer ready notification callbacks.
*
@@ -1319,10 +1343,12 @@
* include any header data.
*
* @param streamParams Structure with encoder parameters
+ * @param codecConfigs List to be filled with codec config buffers
* @return Returns array of encoded frames information for each frame.
*/
protected ArrayList<MediaCodec.BufferInfo> encode(
- EncoderOutputStreamParameters streamParams) throws Exception {
+ EncoderOutputStreamParameters streamParams,
+ ArrayList<ByteBuffer> codecConfigs) throws Exception {
ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
Log.d(TAG, "Source resolution: "+streamParams.frameWidth + " x " +
@@ -1452,6 +1478,12 @@
Log.d(TAG, "----Output EOS ");
sawOutputEOS = true;
}
+ if ((out.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
+ Log.d(TAG, "Storing codec config separately");
+ codecConfigs.add(
+ ByteBuffer.allocate(out.buffer.length).put(out.buffer));
+ out.buffer = new byte[0];
+ }
if (out.buffer.length > 0) {
// Save frame
@@ -1493,10 +1525,12 @@
* include any header data.
*
* @param streamParams Structure with encoder parameters
+ * @param codecConfigs List to be filled with codec config buffers
* @return Returns array of encoded frames information for each frame.
*/
protected ArrayList<MediaCodec.BufferInfo> encodeAsync(
- EncoderOutputStreamParameters streamParams) throws Exception {
+ EncoderOutputStreamParameters streamParams,
+ ArrayList<ByteBuffer> codecConfigs) throws Exception {
if (!streamParams.runInLooperThread) {
throw new RuntimeException("encodeAsync should run with a looper thread!");
}
@@ -1548,7 +1582,7 @@
MediaEncoderAsync codec = new MediaEncoderAsync();
MediaEncoderAsyncHelper helper = new MediaEncoderAsyncHelper(
- streamParams, properties, bufferInfos, ivf);
+ streamParams, properties, bufferInfos, ivf, codecConfigs);
codec.setAsyncHelper(helper);
codec.createCodec(0, properties.codecName, format,
@@ -1577,13 +1611,15 @@
* @param srcFrameWidth Frame width of input yuv file
* @param srcFrameHeight Frame height of input yuv file
* @param encodingParams Encoder parameters
+ * @param codecConfigs List to be filled with codec config buffers
* @return Returns 2D array of encoded frames information for each stream and
* for each frame.
*/
protected ArrayList<ArrayList<MediaCodec.BufferInfo>> encodeSimulcast(
int srcFrameWidth,
int srcFrameHeight,
- ArrayList<EncoderOutputStreamParameters> encodingParams) throws Exception {
+ ArrayList<EncoderOutputStreamParameters> encodingParams,
+ ArrayList<ArrayList<ByteBuffer>> codecConfigs) throws Exception {
int numEncoders = encodingParams.size();
// Create arrays of input/output, formats, bitrates etc
@@ -1748,6 +1784,12 @@
Log.d(TAG, "----Enc" + i + ". Output EOS ");
sawOutputEOS[i] = true;
}
+ if ((out.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
+ Log.d(TAG, "----Enc" + i + ". Storing codec config separately");
+ codecConfigs.get(i).add(
+ ByteBuffer.allocate(out.buffer.length).put(out.buffer));
+ out.buffer = new byte[0];
+ }
if (out.buffer.length > 0) {
// Save frame
diff --git a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
index 81e6a4c..e01412e 100644
--- a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
@@ -1241,17 +1241,29 @@
public void testGoogVP9FlexMinMin() { minmin(googVP9(), true /* flex */); }
public void testGoogVP9SurfMinMin() { minmin(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexMinMin() { minmin(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfMinMin() { minmin(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexMinMin() { minmin(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfMinMin() { minmin(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexMinMin() { minmin(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfMinMin() { minmin(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexMinMin() { minmin(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfMinMin() { minmin(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexMinMin() { minmin(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfMinMin() { minmin(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexMinMin() { minmin(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfMinMin() { minmin(otherVP9(), false /* flex */); }
public void testGoogH265FlexMinMax() { minmax(googH265(), true /* flex */); }
@@ -1267,17 +1279,29 @@
public void testGoogVP9FlexMinMax() { minmax(googVP9(), true /* flex */); }
public void testGoogVP9SurfMinMax() { minmax(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexMinMax() { minmax(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfMinMax() { minmax(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexMinMax() { minmax(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfMinMax() { minmax(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexMinMax() { minmax(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfMinMax() { minmax(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexMinMax() { minmax(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfMinMax() { minmax(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexMinMax() { minmax(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfMinMax() { minmax(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexMinMax() { minmax(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfMinMax() { minmax(otherVP9(), false /* flex */); }
public void testGoogH265FlexMaxMin() { maxmin(googH265(), true /* flex */); }
@@ -1293,17 +1317,29 @@
public void testGoogVP9FlexMaxMin() { maxmin(googVP9(), true /* flex */); }
public void testGoogVP9SurfMaxMin() { maxmin(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexMaxMin() { maxmin(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfMaxMin() { maxmin(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexMaxMin() { maxmin(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfMaxMin() { maxmin(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexMaxMin() { maxmin(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfMaxMin() { maxmin(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexMaxMin() { maxmin(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfMaxMin() { maxmin(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexMaxMin() { maxmin(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfMaxMin() { maxmin(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexMaxMin() { maxmin(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfMaxMin() { maxmin(otherVP9(), false /* flex */); }
public void testGoogH265FlexMaxMax() { maxmax(googH265(), true /* flex */); }
@@ -1319,17 +1355,29 @@
public void testGoogVP9FlexMaxMax() { maxmax(googVP9(), true /* flex */); }
public void testGoogVP9SurfMaxMax() { maxmax(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexMaxMax() { maxmax(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfMaxMax() { maxmax(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexMaxMax() { maxmax(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfMaxMax() { maxmax(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexMaxMax() { maxmax(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfMaxMax() { maxmax(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexMaxMax() { maxmax(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfMaxMax() { maxmax(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexMaxMax() { maxmax(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfMaxMax() { maxmax(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexMaxMax() { maxmax(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfMaxMax() { maxmax(otherVP9(), false /* flex */); }
public void testGoogH265FlexNearMinMin() { nearminmin(googH265(), true /* flex */); }
@@ -1345,17 +1393,29 @@
public void testGoogVP9FlexNearMinMin() { nearminmin(googVP9(), true /* flex */); }
public void testGoogVP9SurfNearMinMin() { nearminmin(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexNearMinMin() { nearminmin(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfNearMinMin() { nearminmin(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexNearMinMin() { nearminmin(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfNearMinMin() { nearminmin(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexNearMinMin() { nearminmin(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfNearMinMin() { nearminmin(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexNearMinMin() { nearminmin(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfNearMinMin() { nearminmin(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexNearMinMin() { nearminmin(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfNearMinMin() { nearminmin(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexNearMinMin() { nearminmin(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfNearMinMin() { nearminmin(otherVP9(), false /* flex */); }
public void testGoogH265FlexNearMinMax() { nearminmax(googH265(), true /* flex */); }
@@ -1371,17 +1431,29 @@
public void testGoogVP9FlexNearMinMax() { nearminmax(googVP9(), true /* flex */); }
public void testGoogVP9SurfNearMinMax() { nearminmax(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexNearMinMax() { nearminmax(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfNearMinMax() { nearminmax(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexNearMinMax() { nearminmax(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfNearMinMax() { nearminmax(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexNearMinMax() { nearminmax(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfNearMinMax() { nearminmax(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexNearMinMax() { nearminmax(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfNearMinMax() { nearminmax(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexNearMinMax() { nearminmax(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfNearMinMax() { nearminmax(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexNearMinMax() { nearminmax(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfNearMinMax() { nearminmax(otherVP9(), false /* flex */); }
public void testGoogH265FlexNearMaxMin() { nearmaxmin(googH265(), true /* flex */); }
@@ -1397,17 +1469,29 @@
public void testGoogVP9FlexNearMaxMin() { nearmaxmin(googVP9(), true /* flex */); }
public void testGoogVP9SurfNearMaxMin() { nearmaxmin(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexNearMaxMin() { nearmaxmin(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfNearMaxMin() { nearmaxmin(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexNearMaxMin() { nearmaxmin(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfNearMaxMin() { nearmaxmin(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexNearMaxMin() { nearmaxmin(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfNearMaxMin() { nearmaxmin(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexNearMaxMin() { nearmaxmin(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfNearMaxMin() { nearmaxmin(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexNearMaxMin() { nearmaxmin(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfNearMaxMin() { nearmaxmin(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexNearMaxMin() { nearmaxmin(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfNearMaxMin() { nearmaxmin(otherVP9(), false /* flex */); }
public void testGoogH265FlexNearMaxMax() { nearmaxmax(googH265(), true /* flex */); }
@@ -1423,17 +1507,29 @@
public void testGoogVP9FlexNearMaxMax() { nearmaxmax(googVP9(), true /* flex */); }
public void testGoogVP9SurfNearMaxMax() { nearmaxmax(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexNearMaxMax() { nearmaxmax(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfNearMaxMax() { nearmaxmax(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexNearMaxMax() { nearmaxmax(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfNearMaxMax() { nearmaxmax(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexNearMaxMax() { nearmaxmax(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfNearMaxMax() { nearmaxmax(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexNearMaxMax() { nearmaxmax(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfNearMaxMax() { nearmaxmax(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexNearMaxMax() { nearmaxmax(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfNearMaxMax() { nearmaxmax(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexNearMaxMax() { nearmaxmax(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfNearMaxMax() { nearmaxmax(otherVP9(), false /* flex */); }
public void testGoogH265FlexArbitraryW() { arbitraryw(googH265(), true /* flex */); }
@@ -1449,17 +1545,29 @@
public void testGoogVP9FlexArbitraryW() { arbitraryw(googVP9(), true /* flex */); }
public void testGoogVP9SurfArbitraryW() { arbitraryw(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexArbitraryW() { arbitraryw(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfArbitraryW() { arbitraryw(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexArbitraryW() { arbitraryw(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfArbitraryW() { arbitraryw(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexArbitraryW() { arbitraryw(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfArbitraryW() { arbitraryw(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexArbitraryW() { arbitraryw(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfArbitraryW() { arbitraryw(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexArbitraryW() { arbitraryw(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfArbitraryW() { arbitraryw(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexArbitraryW() { arbitraryw(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfArbitraryW() { arbitraryw(otherVP9(), false /* flex */); }
public void testGoogH265FlexArbitraryH() { arbitraryh(googH265(), true /* flex */); }
@@ -1475,17 +1583,29 @@
public void testGoogVP9FlexArbitraryH() { arbitraryh(googVP9(), true /* flex */); }
public void testGoogVP9SurfArbitraryH() { arbitraryh(googVP9(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexArbitraryH() { arbitraryh(otherH265(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfArbitraryH() { arbitraryh(otherH265(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264FlexArbitraryH() { arbitraryh(otherH264(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264SurfArbitraryH() { arbitraryh(otherH264(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexArbitraryH() { arbitraryh(otherH263(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfArbitraryH() { arbitraryh(otherH263(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexArbitraryH() { arbitraryh(otherMpeg4(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfArbitraryH() { arbitraryh(otherMpeg4(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexArbitraryH() { arbitraryh(otherVP8(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfArbitraryH() { arbitraryh(otherVP8(), false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexArbitraryH() { arbitraryh(otherVP9(), true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfArbitraryH() { arbitraryh(otherVP9(), false /* flex */); }
public void testGoogH265FlexQCIF() { specific(googH265(), 176, 144, true /* flex */); }
@@ -1503,19 +1623,31 @@
public void testGoogVP9FlexQCIF() { specific(googVP9(), 176, 144, true /* flex */); }
public void testGoogVP9SurfQCIF() { specific(googVP9(), 176, 144, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265FlexQCIF() { specific(otherH265(), 176, 144, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265SurfQCIF() { specific(otherH265(), 176, 144, false /* flex */); }
+ @NonMediaMainlineTest
@SmallTest
public void testOtherH264FlexQCIF() { specific(otherH264(), 176, 144, true /* flex */); }
+ @NonMediaMainlineTest
@SmallTest
public void testOtherH264SurfQCIF() { specific(otherH264(), 176, 144, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263FlexQCIF() { specific(otherH263(), 176, 144, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263SurfQCIF() { specific(otherH263(), 176, 144, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4FlexQCIF() { specific(otherMpeg4(), 176, 144, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4SurfQCIF() { specific(otherMpeg4(), 176, 144, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8FlexQCIF() { specific(otherVP8(), 176, 144, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8SurfQCIF() { specific(otherVP8(), 176, 144, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9FlexQCIF() { specific(otherVP9(), 176, 144, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9SurfQCIF() { specific(otherVP9(), 176, 144, false /* flex */); }
public void testGoogH265Flex480p() { specific(googH265(), 720, 480, true /* flex */); }
@@ -1531,17 +1663,29 @@
public void testGoogVP9Flex480p() { specific(googVP9(), 720, 480, true /* flex */); }
public void testGoogVP9Surf480p() { specific(googVP9(), 720, 480, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265Flex480p() { specific(otherH265(), 720, 480, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265Surf480p() { specific(otherH265(), 720, 480, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264Flex480p() { specific(otherH264(), 720, 480, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264Surf480p() { specific(otherH264(), 720, 480, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263Flex480p() { specific(otherH263(), 720, 480, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263Surf480p() { specific(otherH263(), 720, 480, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4Flex480p() { specific(otherMpeg4(), 720, 480, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4Surf480p() { specific(otherMpeg4(), 720, 480, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8Flex480p() { specific(otherVP8(), 720, 480, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8Surf480p() { specific(otherVP8(), 720, 480, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9Flex480p() { specific(otherVP9(), 720, 480, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9Surf480p() { specific(otherVP9(), 720, 480, false /* flex */); }
// even though H.263 and MPEG-4 are not defined for 720p or 1080p
@@ -1560,17 +1704,29 @@
public void testGoogVP9Flex720p() { specific(googVP9(), 1280, 720, true /* flex */); }
public void testGoogVP9Surf720p() { specific(googVP9(), 1280, 720, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265Flex720p() { specific(otherH265(), 1280, 720, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265Surf720p() { specific(otherH265(), 1280, 720, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264Flex720p() { specific(otherH264(), 1280, 720, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264Surf720p() { specific(otherH264(), 1280, 720, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263Flex720p() { specific(otherH263(), 1280, 720, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263Surf720p() { specific(otherH263(), 1280, 720, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4Flex720p() { specific(otherMpeg4(), 1280, 720, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4Surf720p() { specific(otherMpeg4(), 1280, 720, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8Flex720p() { specific(otherVP8(), 1280, 720, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8Surf720p() { specific(otherVP8(), 1280, 720, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9Flex720p() { specific(otherVP9(), 1280, 720, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9Surf720p() { specific(otherVP9(), 1280, 720, false /* flex */); }
public void testGoogH265Flex1080p() { specific(googH265(), 1920, 1080, true /* flex */); }
@@ -1586,17 +1742,29 @@
public void testGoogVP9Flex1080p() { specific(googVP9(), 1920, 1080, true /* flex */); }
public void testGoogVP9Surf1080p() { specific(googVP9(), 1920, 1080, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265Flex1080p() { specific(otherH265(), 1920, 1080, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH265Surf1080p() { specific(otherH265(), 1920, 1080, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264Flex1080p() { specific(otherH264(), 1920, 1080, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH264Surf1080p() { specific(otherH264(), 1920, 1080, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263Flex1080p() { specific(otherH263(), 1920, 1080, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherH263Surf1080p() { specific(otherH263(), 1920, 1080, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4Flex1080p() { specific(otherMpeg4(), 1920, 1080, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherMpeg4Surf1080p() { specific(otherMpeg4(), 1920, 1080, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8Flex1080p() { specific(otherVP8(), 1920, 1080, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP8Surf1080p() { specific(otherVP8(), 1920, 1080, false /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9Flex1080p() { specific(otherVP9(), 1920, 1080, true /* flex */); }
+ @NonMediaMainlineTest
public void testOtherVP9Surf1080p() { specific(otherVP9(), 1920, 1080, false /* flex */); }
public void testGoogH265Flex360pWithIntraRefresh() {
@@ -1619,105 +1787,130 @@
intraRefresh(googVP8(), 480, 360);
}
+ @NonMediaMainlineTest
public void testOtherH265Flex360pWithIntraRefresh() {
intraRefresh(otherH265(), 480, 360);
}
+ @NonMediaMainlineTest
public void testOtherH264Flex360pWithIntraRefresh() {
intraRefresh(otherH264(), 480, 360);
}
+ @NonMediaMainlineTest
public void testOtherH263FlexQCIFWithIntraRefresh() {
intraRefresh(otherH263(), 176, 120);
}
+ @NonMediaMainlineTest
public void testOtherMpeg4Flex360pWithIntraRefresh() {
intraRefresh(otherMpeg4(), 480, 360);
}
+ @NonMediaMainlineTest
public void testOtherVP8Flex360pWithIntraRefresh() {
intraRefresh(otherVP8(), 480, 360);
}
// Tests encoder profiles required by CDD.
// H264
+ @NonMediaMainlineTest
public void testH264LowQualitySDSupport() {
support(h264(), 320, 240, 20, 384 * 1000);
}
+ @NonMediaMainlineTest
public void testH264HighQualitySDSupport() {
support(h264(), 720, 480, 30, 2 * 1000000);
}
+ @NonMediaMainlineTest
public void testH264FlexQVGA20fps384kbps() {
detailed(h264(), 320, 240, 20, 384 * 1000, true /* flex */);
}
+ @NonMediaMainlineTest
public void testH264SurfQVGA20fps384kbps() {
detailed(h264(), 320, 240, 20, 384 * 1000, false /* flex */);
}
+ @NonMediaMainlineTest
public void testH264Flex480p30fps2Mbps() {
detailed(h264(), 720, 480, 30, 2 * 1000000, true /* flex */);
}
+ @NonMediaMainlineTest
public void testH264Surf480p30fps2Mbps() {
detailed(h264(), 720, 480, 30, 2 * 1000000, false /* flex */);
}
+ @NonMediaMainlineTest
public void testH264Flex720p30fps4Mbps() {
detailed(h264(), 1280, 720, 30, 4 * 1000000, true /* flex */);
}
+ @NonMediaMainlineTest
public void testH264Surf720p30fps4Mbps() {
detailed(h264(), 1280, 720, 30, 4 * 1000000, false /* flex */);
}
+ @NonMediaMainlineTest
public void testH264Flex1080p30fps10Mbps() {
detailed(h264(), 1920, 1080, 30, 10 * 1000000, true /* flex */);
}
+ @NonMediaMainlineTest
public void testH264Surf1080p30fps10Mbps() {
detailed(h264(), 1920, 1080, 30, 10 * 1000000, false /* flex */);
}
// VP8
+ @NonMediaMainlineTest
public void testVP8LowQualitySDSupport() {
support(vp8(), 320, 180, 30, 800 * 1000);
}
+ @NonMediaMainlineTest
public void testVP8HighQualitySDSupport() {
support(vp8(), 640, 360, 30, 2 * 1000000);
}
+ @NonMediaMainlineTest
public void testVP8Flex180p30fps800kbps() {
detailed(vp8(), 320, 180, 30, 800 * 1000, true /* flex */);
}
+ @NonMediaMainlineTest
public void testVP8Surf180p30fps800kbps() {
detailed(vp8(), 320, 180, 30, 800 * 1000, false /* flex */);
}
+ @NonMediaMainlineTest
public void testVP8Flex360p30fps2Mbps() {
detailed(vp8(), 640, 360, 30, 2 * 1000000, true /* flex */);
}
+ @NonMediaMainlineTest
public void testVP8Surf360p30fps2Mbps() {
detailed(vp8(), 640, 360, 30, 2 * 1000000, false /* flex */);
}
+ @NonMediaMainlineTest
public void testVP8Flex720p30fps4Mbps() {
detailed(vp8(), 1280, 720, 30, 4 * 1000000, true /* flex */);
}
+ @NonMediaMainlineTest
public void testVP8Surf720p30fps4Mbps() {
detailed(vp8(), 1280, 720, 30, 4 * 1000000, false /* flex */);
}
+ @NonMediaMainlineTest
public void testVP8Flex1080p30fps10Mbps() {
detailed(vp8(), 1920, 1080, 30, 10 * 1000000, true /* flex */);
}
+ @NonMediaMainlineTest
public void testVP8Surf1080p30fps10Mbps() {
detailed(vp8(), 1920, 1080, 30, 10 * 1000000, false /* flex */);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java
index 17b79d0..0505d8b 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java
@@ -36,6 +36,7 @@
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+@NonMediaMainlineTest
public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
private static final String TAG = "MediaRecorderStressTest";
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/NonMediaMainlineTest.java b/tests/tests/mediastress/src/android/mediastress/cts/NonMediaMainlineTest.java
new file mode 100644
index 0000000..29f9131
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/NonMediaMainlineTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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.mediastress.cts;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for tests that are not related to media mainline.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface NonMediaMainlineTest {
+}
diff --git a/tests/tests/midi/AndroidTest.xml b/tests/tests/midi/AndroidTest.xml
index f8fa763..707e0be 100644
--- a/tests/tests/midi/AndroidTest.xml
+++ b/tests/tests/midi/AndroidTest.xml
@@ -16,8 +16,9 @@
<configuration description="Config for CTS MIDI test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="media" />
- <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
<option name="user-type" value="system" />
</target_preparer>
diff --git a/tests/tests/mimemap/src/android/content/type/cts/MimeMapTest.java b/tests/tests/mimemap/src/android/content/type/cts/MimeMapTest.java
index f86ee49..cab5790 100644
--- a/tests/tests/mimemap/src/android/content/type/cts/MimeMapTest.java
+++ b/tests/tests/mimemap/src/android/content/type/cts/MimeMapTest.java
@@ -254,14 +254,7 @@
Objects.requireNonNull(mimeType);
assertEquals(mimeType, webkitMap.getMimeTypeFromExtension(extension));
assertTrue(webkitMap.hasExtension(extension));
-
- // Extensions should never start with '.', make sure this is not the case ahead
- // of the subsequent check.
- assertFalse(extension.startsWith("."));
- // Relax this check for extensions that contain "." because of http://b/141880067
- if (!extension.contains(".")) {
- assertEquals(mimeType, urlConnectionMap.getContentTypeFor("filename." + extension));
- }
+ assertEquals(mimeType, urlConnectionMap.getContentTypeFor("filename." + extension));
}
for (String mimeType : mimeMap.mimeTypes()) {
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
index 9d9b2a3..d943231 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
@@ -25,7 +25,6 @@
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
-import android.net.wifi.WifiSsid;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
@@ -132,7 +131,7 @@
SupplicantState.isValidState(wifiInfo.getSupplicantState());
WifiInfo.getDetailedStateOf(SupplicantState.DISCONNECTED);
String ssid = wifiInfo.getSSID();
- if (!ssid.startsWith("0x") && !ssid.equals(WifiSsid.NONE)) {
+ if (!ssid.startsWith("0x") && !ssid.equals(WifiManager.UNKNOWN_SSID)) {
// Non-hex string should be quoted
assertTrue(ssid.charAt(0) == '"');
assertTrue(ssid.charAt(ssid.length() - 1) == '"');
diff --git a/tests/tests/opengl/src/android/opengl/cts/EglConfigCtsActivity.java b/tests/tests/opengl/src/android/opengl/cts/EglConfigCtsActivity.java
index cef9e2f..1b8cf77 100644
--- a/tests/tests/opengl/src/android/opengl/cts/EglConfigCtsActivity.java
+++ b/tests/tests/opengl/src/android/opengl/cts/EglConfigCtsActivity.java
@@ -16,83 +16,176 @@
package android.opengl.cts;
+import static org.junit.Assert.assertTrue;
+
import android.app.Activity;
-import android.content.Intent;
+import android.content.Context;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
+import android.util.Log;
import android.view.WindowManager;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+
/**
* {@link Activity} with a {@link GLSurfaceView} that chooses a specific configuration.
*/
public class EglConfigCtsActivity extends Activity {
+ private final String TAG = this.getClass().getSimpleName();
+
public static final String CONFIG_ID_EXTRA = "eglConfigId";
public static final String CONTEXT_CLIENT_VERSION_EXTRA = "eglContextClientVersion";
+ private static final int EGL_OPENGL_ES_BIT = 0x1;
+ private static final int EGL_OPENGL_ES2_BIT = 0x4;
+
private EglConfigGLSurfaceView mView;
private CountDownLatch mFinishedDrawing;
+ private CountDownLatch mFinishedTesting;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- int configId = getConfigId();
- int contextClientVersion = getContextClientVersion();
- setTitle("EGL Config Id: " + configId + " Client Version: " + contextClientVersion);
// Dismiss keyguard and keep screen on while this test is on.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- mFinishedDrawing = new CountDownLatch(1);
- mView = new EglConfigGLSurfaceView(this, configId, contextClientVersion, new Runnable() {
- @Override
- public void run() {
- mFinishedDrawing.countDown();
- }
- });
- setContentView(mView);
- }
-
- private int getConfigId() {
- Intent intent = getIntent();
- if (intent != null) {
- return intent.getIntExtra(CONFIG_ID_EXTRA, 0);
- } else {
- return 0;
- }
- }
-
- private int getContextClientVersion() {
- Intent intent = getIntent();
- if (intent != null) {
- return intent.getIntExtra(CONTEXT_CLIENT_VERSION_EXTRA, 0);
- } else {
- return 0;
+ int[] configIds = getEglConfigIds(EGL_OPENGL_ES_BIT);
+ int[] configIds2 = getEglConfigIds(EGL_OPENGL_ES2_BIT);
+ assertTrue(configIds.length + configIds2.length > 0);
+ mFinishedTesting = new CountDownLatch(configIds.length + configIds2.length);
+ try {
+ runConfigTests(configIds, 1);
+ runConfigTests(configIds2, 2);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Caught exception");
}
}
@Override
protected void onResume() {
super.onResume();
- mView.onResume();
+ if (mView != null)
+ {
+ mView.onResume();
+ }
}
@Override
protected void onPause() {
super.onPause();
- mView.onPause();
+ if (mView != null)
+ {
+ mView.onPause();
+ }
}
- public void waitToFinishDrawing() throws InterruptedException {
- if (!mFinishedDrawing.await(3, TimeUnit.SECONDS)) {
- throw new IllegalStateException("Coudn't finish drawing frames!");
+ private void runConfigTests(int[] configIds, int contextClientVersion)
+ throws InterruptedException {
+ Context context = this;
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ for (int configId : configIds) {
+ mFinishedDrawing = new CountDownLatch(1);
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ setTitle("EGL Config Id: " + configId + " Client Version: " + contextClientVersion);
+ mView = new EglConfigGLSurfaceView(context, configId, contextClientVersion, new Runnable() {
+ @Override
+ public void run() {
+ mFinishedDrawing.countDown();
+ }
+ });
+ setContentView(mView);
+ }
+ });
+
+ try {
+ waitToFinishDrawing();
+ } catch (Exception e) {
+ Log.e(TAG, "Timed out!");
+ }
+
+ mFinishedTesting.countDown();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ private void waitToFinishDrawing() throws InterruptedException {
+ if (!mFinishedDrawing.await(5, TimeUnit.SECONDS)) {
+ throw new IllegalStateException("Couldn't finish drawing frames!");
+ }
+ }
+
+ void waitToFinishTesting() throws InterruptedException {
+ if (!mFinishedTesting.await(300, TimeUnit.SECONDS)) {
+ throw new IllegalStateException("Couldn't finish testing!");
+ }
+ }
+
+ private static int[] getEglConfigIds(int renderableType) {
+ EGL10 egl = (EGL10) EGLContext.getEGL();
+ EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ int[] numConfigs = new int[1];
+
+ int[] attributeList = new int[] {
+ EGL10.EGL_RENDERABLE_TYPE, renderableType,
+
+ // Avoid configs like RGBA0008 which crash even though they have the window bit set.
+ EGL10.EGL_RED_SIZE, 1,
+ EGL10.EGL_GREEN_SIZE, 1,
+ EGL10.EGL_BLUE_SIZE, 1,
+
+ EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
+ EGL10.EGL_NONE
+ };
+
+ if (egl.eglInitialize(display, null)) {
+ try {
+ if (egl.eglChooseConfig(display, attributeList, null, 0, numConfigs)) {
+ EGLConfig[] configs = new EGLConfig[numConfigs[0]];
+ if (egl.eglChooseConfig(display, attributeList, configs, configs.length,
+ numConfigs)) {
+ int[] configIds = new int[numConfigs[0]];
+ for (int i = 0; i < numConfigs[0]; i++) {
+ int[] value = new int[1];
+ if (egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_CONFIG_ID,
+ value)) {
+ configIds[i] = value[0];
+ } else {
+ throw new IllegalStateException("Couldn't call eglGetConfigAttrib");
+ }
+ }
+ return configIds;
+ } else {
+ throw new IllegalStateException("Couldn't call eglChooseConfig (1)");
+ }
+ } else {
+ throw new IllegalStateException("Couldn't call eglChooseConfig (2)");
+ }
+ } finally {
+ egl.eglTerminate(display);
+ }
+ } else {
+ throw new IllegalStateException("Couldn't initialize EGL.");
}
}
}
diff --git a/tests/tests/opengl/src/android/opengl/cts/EglConfigTest.java b/tests/tests/opengl/src/android/opengl/cts/EglConfigTest.java
index 3e5565e..613456a 100644
--- a/tests/tests/opengl/src/android/opengl/cts/EglConfigTest.java
+++ b/tests/tests/opengl/src/android/opengl/cts/EglConfigTest.java
@@ -25,6 +25,7 @@
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import static androidx.test.internal.util.Checks.checkState;
import org.junit.Before;
import org.junit.Rule;
@@ -36,14 +37,16 @@
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
+import android.util.Log;
+import java.lang.Runnable;
+
/**
* Test that gets a list of EGL configurations and tries to use each one in a GLSurfaceView.
*/
@LargeTest
@RunWith(AndroidJUnit4.class)
public class EglConfigTest {
- private static final int EGL_OPENGL_ES_BIT = 0x1;
- private static final int EGL_OPENGL_ES2_BIT = 0x4;
+ private final String TAG = this.getClass().getSimpleName();
private Instrumentation mInstrumentation;
@@ -58,75 +61,11 @@
@Test
public void testEglConfigs() throws Exception {
- int[] configIds = getEglConfigIds(EGL_OPENGL_ES_BIT);
- int[] configIds2 = getEglConfigIds(EGL_OPENGL_ES2_BIT);
- assertTrue(configIds.length + configIds2.length > 0);
- runConfigTests(configIds, 1);
- runConfigTests(configIds2, 2);
- }
-
- private void runConfigTests(int[] configIds, int contextClientVersion)
- throws InterruptedException {
- for (int configId : configIds) {
- Intent intent = new Intent(InstrumentationRegistry.getTargetContext(),
- EglConfigCtsActivity.class);
- intent.putExtra(EglConfigCtsActivity.CONFIG_ID_EXTRA, configId);
- intent.putExtra(EglConfigCtsActivity.CONTEXT_CLIENT_VERSION_EXTRA,
- contextClientVersion);
- EglConfigCtsActivity activity = mActivityRule.launchActivity(intent);
- activity.waitToFinishDrawing();
- // TODO(b/30948621): Remove the sleep below once b/30948621 is fixed.
- Thread.sleep(500);
- activity.finish();
- mInstrumentation.waitForIdleSync();
- }
- }
-
- private static int[] getEglConfigIds(int renderableType) {
- EGL10 egl = (EGL10) EGLContext.getEGL();
- EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
- int[] numConfigs = new int[1];
-
- int[] attributeList = new int[] {
- EGL10.EGL_RENDERABLE_TYPE, renderableType,
-
- // Avoid configs like RGBA0008 which crash even though they have the window bit set.
- EGL10.EGL_RED_SIZE, 1,
- EGL10.EGL_GREEN_SIZE, 1,
- EGL10.EGL_BLUE_SIZE, 1,
-
- EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
- EGL10.EGL_NONE
- };
-
- if (egl.eglInitialize(display, null)) {
- try {
- if (egl.eglChooseConfig(display, attributeList, null, 0, numConfigs)) {
- EGLConfig[] configs = new EGLConfig[numConfigs[0]];
- if (egl.eglChooseConfig(display, attributeList, configs, configs.length,
- numConfigs)) {
- int[] configIds = new int[numConfigs[0]];
- for (int i = 0; i < numConfigs[0]; i++) {
- int[] value = new int[1];
- if (egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_CONFIG_ID,
- value)) {
- configIds[i] = value[0];
- } else {
- throw new IllegalStateException("Couldn't call eglGetConfigAttrib");
- }
- }
- return configIds;
- } else {
- throw new IllegalStateException("Couldn't call eglChooseConfig (1)");
- }
- } else {
- throw new IllegalStateException("Couldn't call eglChooseConfig (2)");
- }
- } finally {
- egl.eglTerminate(display);
- }
- } else {
- throw new IllegalStateException("Couldn't initialize EGL.");
- }
+ Intent intent = new Intent(InstrumentationRegistry.getTargetContext(),
+ EglConfigCtsActivity.class);
+ EglConfigCtsActivity activity = mActivityRule.launchActivity(intent);
+ activity.waitToFinishTesting();
+ activity.finish();
+ mInstrumentation.waitForIdleSync();
}
}
diff --git a/tests/tests/os/src/android/os/cts/WorkSourceTest.java b/tests/tests/os/src/android/os/cts/WorkSourceTest.java
index 9b6fa80..afcb64d 100644
--- a/tests/tests/os/src/android/os/cts/WorkSourceTest.java
+++ b/tests/tests/os/src/android/os/cts/WorkSourceTest.java
@@ -106,7 +106,7 @@
failWorkSource(op, ws, uids);
}
for (int i=0; i<uids.length; i++) {
- if (uids[i] != ws.get(i)) {
+ if (uids[i] != ws.getUid(i)) {
failWorkSource(op, ws, uids);
}
}
@@ -126,7 +126,7 @@
failWorkSource(op, ws, uids, names);
}
for (int i=0; i<uids.length; i++) {
- if (uids[i] != ws.get(i) || !names[i].equals(ws.getName(i))) {
+ if (uids[i] != ws.getUid(i) || !names[i].equals(ws.getPackageName(i))) {
failWorkSource(op, ws, uids, names);
}
}
@@ -483,4 +483,42 @@
new int[] { },
true);
}
+
+ public void testIsEmptyByDefault() {
+ WorkSource ws = new WorkSource();
+ assertTrue("isEmpty false for empty WorkSource", ws.isEmpty());
+ }
+
+ public void testIsEmptyOnClear() {
+ WorkSource ws = wsNew(new int[] {1, 2, 3}, new String[] {"a", "aa", "aaa"});
+ assertFalse(ws.isEmpty());
+ ws.clear();
+ assertTrue(ws.isEmpty());
+ }
+
+ public void testWithoutNames() {
+ WorkSource ws = wsNew(
+ new int[] {10, 12, 12, 15, 15, 17},
+ new String[] {"a", "b", "c", "d", "e", "f"});
+ WorkSource wsWithoutNames = ws.withoutNames();
+
+ int[] expectedUids = new int[] {10, 12, 15, 17};
+ if (expectedUids.length != wsWithoutNames.size()) {
+ failWorkSource("withoutNames", wsWithoutNames, expectedUids);
+ }
+ for (int i = 0; i < expectedUids.length; i++) {
+ if (wsWithoutNames.getUid(i) != expectedUids[i]) {
+ failWorkSource("withoutNames", wsWithoutNames, expectedUids);
+ }
+ if (wsWithoutNames.getPackageName(i) != null) {
+ fail("Name " + wsWithoutNames.getPackageName(i) + " found at i = " + i);
+ }
+ }
+ try {
+ wsWithoutNames.add(50, "name");
+ fail("Added name to unnamed worksource");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+ }
}
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 15ab41f..007cb95 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -1547,14 +1547,6 @@
<permission android:name="android.permission.NETWORK_STACK"
android:protectionLevel="signature" />
- <!-- @SystemApi @hide Allows an application to observe network policy changes. -->
- <permission android:name="android.permission.OBSERVE_NETWORK_POLICY"
- android:protectionLevel="signature" />
-
- <!-- @SystemApi @hide Allows applications to register network factory or agent -->
- <permission android:name="android.permission.NETWORK_FACTORY"
- android:protectionLevel="signature" />
-
<!-- Allows Settings and SystemUI to call methods in Networking services
<p>Not for use by third-party or privileged applications.
@hide This should only be used by Settings and SystemUI.
diff --git a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
index e84e3af..26c6cc8 100644
--- a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
+++ b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
@@ -26,6 +26,7 @@
import android.Manifest.permission.CALL_PHONE
import android.Manifest.permission.CAMERA
import android.Manifest.permission.GET_ACCOUNTS
+import android.Manifest.permission.PACKAGE_USAGE_STATS
import android.Manifest.permission.PROCESS_OUTGOING_CALLS
import android.Manifest.permission.READ_CALENDAR
import android.Manifest.permission.READ_CALL_LOG
@@ -89,6 +90,10 @@
fun allAppOpPermissionNeedAnAppOp() {
val platformAppOpPerms = platformPkg.permissions
.filter { (it.protectionFlags and PROTECTION_FLAG_APPOP) != 0 }
+ .filter {
+ // Grandfather incomplete definition of PACKAGE_USAGE_STATS
+ it.name != PACKAGE_USAGE_STATS
+ }
for (perm in platformAppOpPerms) {
assertThat(permissionToOp(perm.name)).named("AppOp for ${perm.name}").isNotNull()
diff --git a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
index e8eb0b2..288c858 100644
--- a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
@@ -27,7 +27,6 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
-import android.os.UserHandle;
import android.os.UserManager;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
@@ -43,6 +42,9 @@
import com.android.compatibility.common.util.Timeout;
+import com.google.common.io.BaseEncoding;
+
+import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@@ -53,6 +55,7 @@
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.util.HashSet;
@@ -362,14 +365,17 @@
}
public static String getRawFileHash(File file) throws Exception {
- final String res = ProviderTestUtils.executeShellCommand(
- "sha1sum " + file.getAbsolutePath(),
- InstrumentationRegistry.getInstrumentation().getUiAutomation());
- if (Pattern.matches("[0-9a-fA-F]{40}.+", res)) {
- return res.substring(0, 40);
- } else {
- throw new FileNotFoundException("Failed to find hash for " + file + "; found " + res);
+ MessageDigest digest = MessageDigest.getInstance("SHA-1");
+ try (InputStream in = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
+ byte[] buf = new byte[4096];
+ int n;
+ while ((n = in.read(buf)) >= 0) {
+ digest.update(buf, 0, n);
+ }
}
+
+ byte[] hash = digest.digest();
+ return BaseEncoding.base16().encode(hash);
}
public static File getRelativeFile(Uri uri) throws Exception {
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStorePendingTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStorePendingTest.java
index ae5674b..961d998 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStorePendingTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStorePendingTest.java
@@ -56,9 +56,9 @@
import org.junit.runners.Parameterized.Parameters;
import java.io.File;
-import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.file.NoSuchFileException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@@ -186,7 +186,7 @@
try {
getRawFileHash(pendingFile);
fail();
- } catch (FileNotFoundException expected) {
+ } catch (NoSuchFileException expected) {
}
}
diff --git a/tests/tests/provider/src/android/provider/cts/settings/Settings_NameValueTableTest.java b/tests/tests/provider/src/android/provider/cts/settings/Settings_NameValueTableTest.java
index d2dbc52..e174469 100644
--- a/tests/tests/provider/src/android/provider/cts/settings/Settings_NameValueTableTest.java
+++ b/tests/tests/provider/src/android/provider/cts/settings/Settings_NameValueTableTest.java
@@ -22,36 +22,23 @@
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
-import android.os.SystemClock;
import android.provider.Settings;
import android.provider.Settings.NameValueTable;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class Settings_NameValueTableTest {
- @BeforeClass
- public static void setUp() throws Exception {
- final String packageName = InstrumentationRegistry.getTargetContext().getPackageName();
- InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(
- "appops set " + packageName + " android:write_settings allow");
- // Wait a beat to persist the change
- SystemClock.sleep(500);
- }
-
- @AfterClass
- public static void tearDown() throws Exception {
- final String packageName = InstrumentationRegistry.getTargetContext().getPackageName();
- InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(
- "appops set " + packageName + " android:write_settings default");
- }
+ @Rule
+ public AdoptShellPermissionsRule shellPermRule = new AdoptShellPermissionsRule();
@Test
public void testPutString() {
diff --git a/tests/tests/role/AndroidTest.xml b/tests/tests/role/AndroidTest.xml
index cf4b1d3..71a4861 100644
--- a/tests/tests/role/AndroidTest.xml
+++ b/tests/tests/role/AndroidTest.xml
@@ -22,6 +22,7 @@
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/tests/systemui/src/android/systemui/cts/WindowInsetsBehaviorTests.java b/tests/tests/systemui/src/android/systemui/cts/WindowInsetsBehaviorTests.java
index 93fc4d9..1a84f34 100644
--- a/tests/tests/systemui/src/android/systemui/cts/WindowInsetsBehaviorTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/WindowInsetsBehaviorTests.java
@@ -16,8 +16,8 @@
package android.systemui.cts;
-import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER;
-import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
+import static android.provider.DeviceConfig.NAMESPACE_ANDROID;
+import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
import static android.view.View.SYSTEM_UI_CLEARABLE_FLAGS;
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
@@ -839,10 +839,10 @@
private static int getPropertyOfMaxExclusionHeight() {
final int[] originalLimitDp = new int[1];
SystemUtil.runWithShellPermissionIdentity(() -> {
- originalLimitDp[0] = DeviceConfig.getInt(NAMESPACE_WINDOW_MANAGER,
+ originalLimitDp[0] = DeviceConfig.getInt(NAMESPACE_ANDROID,
KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, -1);
DeviceConfig.setProperty(
- NAMESPACE_WINDOW_MANAGER,
+ NAMESPACE_ANDROID,
KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP,
Integer.toString(EXCLUSION_LIMIT_DP), false /* makeDefault */);
});
@@ -864,7 +864,7 @@
} finally {
// Restore the value
SystemUtil.runWithShellPermissionIdentity(() -> DeviceConfig.setProperty(
- NAMESPACE_WINDOW_MANAGER,
+ NAMESPACE_ANDROID,
KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP,
(originalLimitDp != -1) ? Integer.toString(originalLimitDp) : null,
false /* makeDefault */));
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 1e1a073..1a8b41e 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -1707,8 +1707,9 @@
assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS);
}
- private static void assertSetOpportunisticInvalidParameter(int value) {
- assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+ private static void assertSetOpportunisticNoOpportunisticSub(int value) {
+ assertThat(value).isEqualTo(
+ TelephonyManager.SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE);
}
/**
@@ -1743,18 +1744,17 @@
ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager,
(tm) -> tm.getOpportunisticSubscriptions());
Consumer<Integer> callbackSuccess = TelephonyManagerTest::assertSetOpportunisticSubSuccess;
- Consumer<Integer> callbackFailure =
- TelephonyManagerTest::assertSetOpportunisticInvalidParameter;
+ Consumer<Integer> callbackNoOpSub =
+ TelephonyManagerTest::assertSetOpportunisticNoOpportunisticSub;
if (subscriptionInfoList == null || subscriptionInfoList.size() == 0) {
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
(tm) -> tm.setPreferredOpportunisticDataSubscription(randomSubId, false,
- AsyncTask.SERIAL_EXECUTOR, callbackFailure));
+ AsyncTask.SERIAL_EXECUTOR, callbackNoOpSub));
// wait for the data change to take effect
waitForMs(500);
subId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
(tm) -> tm.getPreferredOpportunisticDataSubscription());
assertThat(subId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
-
} else {
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
(tm) -> tm.setPreferredOpportunisticDataSubscription(
@@ -1786,6 +1786,11 @@
assertThat(value).isEqualTo(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
}
+ private static void assertUpdateAvailableNetworkNoOpportunisticSub(int value) {
+ assertThat(value).isEqualTo(
+ TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE);
+ }
+
private static boolean checkIfEmergencyNumberListHasSpecificAddress(
List<EmergencyNumber> emergencyNumberList, String address) {
for (EmergencyNumber emergencyNumber : emergencyNumberList) {
@@ -1846,9 +1851,15 @@
int randomSubId = 1;
int activeSubscriptionInfoCount = ShellIdentityUtils.invokeMethodWithShellPermissions(
mSubscriptionManager, (tm) -> tm.getActiveSubscriptionInfoCount());
+ boolean isOpportunisticNetworkEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mTelephonyManager, (tm) -> tm.isOpportunisticNetworkEnabled());
+
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
return;
}
+ if (!isOpportunisticNetworkEnabled) {
+ return;
+ }
if (mTelephonyManager.getPhoneCount() == 1) {
return;
}
@@ -1866,6 +1877,8 @@
TelephonyManagerTest::assertUpdateAvailableNetworkSuccess;
Consumer<Integer> callbackFailure =
TelephonyManagerTest::assertUpdateAvailableNetworkInvalidArguments;
+ Consumer<Integer> callbackNoOpSub =
+ TelephonyManagerTest::assertUpdateAvailableNetworkNoOpportunisticSub;
if (subscriptionInfoList == null || subscriptionInfoList.size() == 0
|| !mSubscriptionManager.isActiveSubscriptionId(
subscriptionInfoList.get(0).getSubscriptionId())) {
@@ -1874,7 +1887,7 @@
availableNetworkInfos.add(availableNetworkInfo);
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
(tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
- AsyncTask.SERIAL_EXECUTOR, callbackFailure));
+ AsyncTask.SERIAL_EXECUTOR, callbackNoOpSub));
// wait for the data change to take effect
waitForMs(500);
// clear all the operations at the end of test.
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index 4bd8e6b..72d3fd1 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -382,6 +382,15 @@
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
+
+ <service
+ android:name="android.view.textclassifier.cts.CtsTextClassifierService"
+ android:exported="true"
+ android:permission="android.permission.BIND_TEXTCLASSIFIER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.textclassifier.TextClassifierService"/>
+ </intent-filter>
+ </service>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/view/AndroidTest.xml b/tests/tests/view/AndroidTest.xml
index 4f53b76..55fa315 100644
--- a/tests/tests/view/AndroidTest.xml
+++ b/tests/tests/view/AndroidTest.xml
@@ -20,6 +20,7 @@
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsQueryTextClassifierServiceActivity.apk" />
<option name="test-file-name" value="CtsViewTestCases.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/view/QueryTextClassifierServiceActivity/Android.bp b/tests/tests/view/QueryTextClassifierServiceActivity/Android.bp
new file mode 100644
index 0000000..e617625
--- /dev/null
+++ b/tests/tests/view/QueryTextClassifierServiceActivity/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2019 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.
+//
+
+android_test_helper_app {
+ name: "CtsQueryTextClassifierServiceActivity",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ srcs: ["src/**/*.java"],
+}
\ No newline at end of file
diff --git a/tests/tests/view/QueryTextClassifierServiceActivity/AndroidManifest.xml b/tests/tests/view/QueryTextClassifierServiceActivity/AndroidManifest.xml
new file mode 100644
index 0000000..f6e49a6
--- /dev/null
+++ b/tests/tests/view/QueryTextClassifierServiceActivity/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.textclassifier.cts2"
+ android:targetSandboxVersion="2">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+
+ <activity android:name=".QueryTextClassifierServiceActivity"
+ android:label="QueryTextClassifierServiceActivity"
+ android:exported="true"
+ android:taskAffinity=".QueryTextClassifierService">
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:label="CTS tests for the TextClassifier Service."
+ android:targetPackage="android.textclassifier.cts2" >
+ </instrumentation>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/view/QueryTextClassifierServiceActivity/src/com/android/textclassifier/cts2/QueryTextClassifierServiceActivity.java b/tests/tests/view/QueryTextClassifierServiceActivity/src/com/android/textclassifier/cts2/QueryTextClassifierServiceActivity.java
new file mode 100644
index 0000000..1a7f9b1
--- /dev/null
+++ b/tests/tests/view/QueryTextClassifierServiceActivity/src/com/android/textclassifier/cts2/QueryTextClassifierServiceActivity.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 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.textclassifier.cts2;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.textclassifier.TextClassificationManager;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextLanguage;
+
+/**
+ * An activity that queries the device's TextClassifierService when started and immediately
+ * terminates itself.
+ */
+public final class QueryTextClassifierServiceActivity extends Activity {
+
+ private static final String TAG = QueryTextClassifierServiceActivity.class.getSimpleName();
+ private PendingIntent mPendingIntent;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Intent intent = getIntent();
+ mPendingIntent = intent.getParcelableExtra("finishBroadcast");
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // Do a TextClassifier call
+ detectLanguageAndFinish();
+ }
+
+ private void detectLanguageAndFinish() {
+ final String text = "An email address is test@example.com.";
+ new Thread(() -> {
+ final TextLanguage.Request textLanguageRequest =
+ new TextLanguage.Request.Builder(text)
+ .build();
+ TextClassifier textClassifier = getClassifier();
+ textClassifier.detectLanguage(textLanguageRequest);
+ // Send finish broadcast
+ if (mPendingIntent != null) {
+ try {
+ mPendingIntent.send();
+ } catch (CanceledException e) {
+ Log.w(TAG, "Pending intent " + mPendingIntent + " canceled");
+ }
+ }
+ finish();
+ }).start();
+ }
+
+ private TextClassifier getClassifier() {
+ final TextClassificationManager tcm = getSystemService(TextClassificationManager.class);
+ return tcm != null ? tcm.getTextClassifier() : TextClassifier.NO_OP;
+ }
+}
diff --git a/tests/tests/view/src/android/view/textclassifier/cts/CtsTextClassifierService.java b/tests/tests/view/src/android/view/textclassifier/cts/CtsTextClassifierService.java
new file mode 100644
index 0000000..52145a9
--- /dev/null
+++ b/tests/tests/view/src/android/view/textclassifier/cts/CtsTextClassifierService.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2019 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.view.textclassifier.cts;
+
+import android.os.CancellationSignal;
+import android.service.textclassifier.TextClassifierService;
+import android.util.Log;
+import android.view.textclassifier.ConversationActions;
+import android.view.textclassifier.SelectionEvent;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassificationContext;
+import android.view.textclassifier.TextClassificationSessionId;
+import android.view.textclassifier.TextClassifierEvent;
+import android.view.textclassifier.TextLanguage;
+import android.view.textclassifier.TextLinks;
+import android.view.textclassifier.TextSelection;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Implementation of {@link TextClassifierService} used in the tests.
+ */
+public final class CtsTextClassifierService extends TextClassifierService {
+
+ private static final String TAG = CtsTextClassifierService.class.getSimpleName();
+ public static final String MY_PACKAGE = "android.view.cts";
+ private static final ArrayList<Throwable> sExceptions = new ArrayList<>();
+ private static final long GENERIC_TIMEOUT_MS = 10_000;
+
+ private static ServiceWatcher sServiceWatcher;
+
+ private final ArrayList<TextClassificationSessionId> mRequestSessions = new ArrayList<>();
+ private final CountDownLatch mRequestLatch = new CountDownLatch(1);
+
+ @NonNull
+ static ServiceWatcher setServiceWatcher() {
+ if (sServiceWatcher == null) {
+ sServiceWatcher = new ServiceWatcher();
+ }
+ return sServiceWatcher;
+ }
+
+ static void clearServiceWatcher() {
+ if (sServiceWatcher != null) {
+ sServiceWatcher.mService = null;
+ sServiceWatcher = null;
+ }
+ }
+
+ @NonNull
+ List<TextClassificationSessionId> getRequestSessions() {
+ return Collections.unmodifiableList(mRequestSessions);
+ }
+
+ void awaitQuery(long timeoutMillis) {
+ try {
+ mRequestLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+
+ /**
+ * Gets the exceptions that were thrown while the service handled requests.
+ */
+ @NonNull
+ public static List<Throwable> getExceptions() throws Exception {
+ return Collections.unmodifiableList(sExceptions);
+ }
+
+ public static void resetStaticState() {
+ sExceptions.clear();
+ if (sServiceWatcher != null) {
+ sServiceWatcher = null;
+ }
+ }
+
+ @Override
+ public void onSuggestSelection(TextClassificationSessionId sessionId,
+ TextSelection.Request request, CancellationSignal cancellationSignal,
+ Callback<TextSelection> callback) {
+ mRequestSessions.add(sessionId);
+ mRequestLatch.countDown();
+ }
+
+ @Override
+ public void onClassifyText(TextClassificationSessionId sessionId,
+ TextClassification.Request request, CancellationSignal cancellationSignal,
+ Callback<TextClassification> callback) {
+ mRequestSessions.add(sessionId);
+ mRequestLatch.countDown();
+ }
+
+ @Override
+ public void onGenerateLinks(TextClassificationSessionId sessionId, TextLinks.Request request,
+ CancellationSignal cancellationSignal, Callback<TextLinks> callback) {
+ mRequestSessions.add(sessionId);
+ mRequestLatch.countDown();
+ }
+
+ @Override
+ public void onDetectLanguage(TextClassificationSessionId sessionId,
+ TextLanguage.Request request, CancellationSignal cancellationSignal,
+ Callback<TextLanguage> callback) {
+ mRequestSessions.add(sessionId);
+ mRequestLatch.countDown();
+ }
+
+ @Override
+ public void onSuggestConversationActions(TextClassificationSessionId sessionId,
+ ConversationActions.Request request, CancellationSignal cancellationSignal,
+ Callback<ConversationActions> callback) {
+ mRequestSessions.add(sessionId);
+ mRequestLatch.countDown();
+ }
+
+ @Override
+ public void onSelectionEvent(TextClassificationSessionId sessionId, SelectionEvent event) {
+ mRequestSessions.add(sessionId);
+ mRequestLatch.countDown();
+ }
+
+ @Override
+ public void onTextClassifierEvent(TextClassificationSessionId sessionId,
+ TextClassifierEvent event) {
+ mRequestSessions.add(sessionId);
+ mRequestLatch.countDown();
+ }
+
+ @Override
+ public void onCreateTextClassificationSession(TextClassificationContext context,
+ TextClassificationSessionId sessionId) {
+ mRequestSessions.add(sessionId);
+ mRequestLatch.countDown();
+ }
+
+ @Override
+ public void onDestroyTextClassificationSession(TextClassificationSessionId sessionId) {
+ mRequestSessions.add(sessionId);
+ mRequestLatch.countDown();
+ }
+
+ @Override
+ public void onConnected() {
+ Log.i(TAG, "onConnected: sServiceWatcher=" + sServiceWatcher);
+
+ if (sServiceWatcher == null) {
+ addException("onConnected() without a watcher");
+ return;
+ }
+
+ if (sServiceWatcher.mService != null) {
+ addException("onConnected(): already created: " + sServiceWatcher);
+ return;
+ }
+
+ sServiceWatcher.mService = this;
+ sServiceWatcher.mCreated.countDown();
+ }
+
+ @Override
+ public void onDisconnected() {
+ Log.i(TAG, "onDisconnected: sServiceWatcher=" + sServiceWatcher);
+
+ if (sServiceWatcher == null) {
+ addException("onDisconnected() without a watcher");
+ return;
+ }
+
+ if (sServiceWatcher.mService == null) {
+ addException("onDisconnected(): no service on %s", sServiceWatcher);
+ return;
+ }
+ sServiceWatcher.mDestroyed.countDown();
+ }
+
+ private static void addException(@NonNull String fmt, @Nullable Object...args) {
+ final String msg = String.format(fmt, args);
+ Log.e(TAG, msg);
+ sExceptions.add(new IllegalStateException(msg));
+ }
+
+ // TODO: add a TestRule which extends TestWatcher
+ public static final class ServiceWatcher {
+ private final CountDownLatch mCreated = new CountDownLatch(1);
+ private final CountDownLatch mDestroyed = new CountDownLatch(1);
+
+ CtsTextClassifierService mService;
+
+ @NonNull
+ public CtsTextClassifierService waitOnConnected() throws InterruptedException {
+ await(mCreated, "not created");
+
+ if (mService == null) {
+ throw new IllegalStateException("not created");
+ }
+ return mService;
+ }
+
+ public void waitOnDisconnected() throws InterruptedException {
+ await(mDestroyed, "not destroyed");
+ }
+
+ private void await(@NonNull CountDownLatch latch, @NonNull String fmt,
+ @Nullable Object... args)
+ throws InterruptedException {
+ final boolean called = latch.await(GENERIC_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ if (!called) {
+ throw new IllegalStateException(String.format(fmt, args)
+ + " in " + GENERIC_TIMEOUT_MS + "ms");
+ }
+ }
+ }
+}
diff --git a/tests/tests/view/src/android/view/textclassifier/cts/TextClassifierServiceSwapTest.java b/tests/tests/view/src/android/view/textclassifier/cts/TextClassifierServiceSwapTest.java
new file mode 100644
index 0000000..ca320c0
--- /dev/null
+++ b/tests/tests/view/src/android/view/textclassifier/cts/TextClassifierServiceSwapTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2019 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.view.textclassifier.cts;
+
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
+import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.support.test.uiautomator.UiDevice;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.textclassifier.cts.CtsTextClassifierService.ServiceWatcher;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.BlockingBroadcastReceiver;
+import com.android.compatibility.common.util.SafeCleanerRule;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for TextClassifierService query related functions.
+ *
+ * <p>
+ * We use a non-standard TextClassifierService for TextClassifierService-related CTS tests. A
+ * non-standard TextClassifierService that is set via device config. This non-standard
+ * TextClassifierService is not defined in the trust TextClassifierService, it should only receive
+ * queries from clients in the same package.
+ */
+@RunWith(AndroidJUnit4.class)
+public class TextClassifierServiceSwapTest {
+ // TODO: Add more tests to verify all the TC APIs call between caller and TCS.
+ private static final String TAG = TextClassifierServiceSwapTest.class.getSimpleName();
+
+ @Rule
+ public final SafeCleanerRule mSafeCleanerRule = new SafeCleanerRule()
+ .add(() -> {
+ return CtsTextClassifierService.getExceptions();
+ });
+
+ private String mOriginalOverrideService;
+ private boolean mOriginalSystemTextClassifierEnabled;
+ private ServiceWatcher mServiceWatcher;
+ private BlockingBroadcastReceiver mFinishReceiver;
+
+ @Before
+ public void setup() throws Exception {
+ prepareDevice();
+ CtsTextClassifierService.resetStaticState();
+ // get original settings
+ mOriginalOverrideService = getOriginalOverrideService();
+ mOriginalSystemTextClassifierEnabled = isSystemTextClassifierEnabled();
+
+ // set system TextClassifier enabled
+ runShellCommand("device_config put textclassifier system_textclassifier_enabled true");
+ // enable test service
+ setService();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mFinishReceiver != null) {
+ mFinishReceiver.unregisterQuietly();
+ }
+ // restore original settings
+ runShellCommand("device_config put textclassifier system_textclassifier_enabled "
+ + mOriginalSystemTextClassifierEnabled);
+ // restore service and make sure service disconnected
+ resetService();
+ }
+
+ @AfterClass
+ public static void resetStates() {
+ CtsTextClassifierService.resetStaticState();
+ }
+
+ private void prepareDevice() {
+ Log.v(TAG, "prepareDevice()");
+ // Unlock screen.
+ runShellCommand("input keyevent KEYCODE_WAKEUP");
+
+ // Dismiss keyguard, in case it's set as "Swipe to unlock".
+ runShellCommand("wm dismiss-keyguard");
+ }
+
+ private String getOriginalOverrideService() {
+ final String deviceConfigSetting = runShellCommand(
+ "device_config get textclassifier textclassifier_service_package_override");
+ if (!TextUtils.isEmpty(deviceConfigSetting) && !deviceConfigSetting.equals("null")) {
+ return deviceConfigSetting;
+ }
+ // TODO: remove the logic when text_classifier_constants is removed
+ final String globalSetting = runShellCommand(
+ "settings get global text_classifier_constants");
+ if (!TextUtils.isEmpty(globalSetting) && globalSetting.contains(
+ "extclassifier_service_package_override")) {
+ return globalSetting.substring(globalSetting.indexOf('=') + 1);
+ }
+ // return default value defined in TextClassificationConstants
+ return null;
+ }
+
+ private boolean isSystemTextClassifierEnabled() {
+ final String deviceConfigSetting = runShellCommand(
+ "device_config get textclassifier system_textclassifier_enabled");
+ if (!TextUtils.isEmpty(deviceConfigSetting) && !deviceConfigSetting.equals("null")) {
+ return deviceConfigSetting.toLowerCase().equals("true");
+ }
+ // TODO: remove the logic when text_classifier_constants is removed
+ final String globalSetting = runShellCommand(
+ "settings get global text_classifier_constants");
+ if (!TextUtils.isEmpty(globalSetting) && globalSetting.contains(
+ "system_textclassifier_enabled")) {
+ return globalSetting.substring(globalSetting.indexOf('=') + 1).toLowerCase().equals(
+ "true");
+ }
+ // return default value defined in TextClassificationConstants
+ return true;
+ }
+
+ private void setService() {
+ mServiceWatcher = CtsTextClassifierService.setServiceWatcher();
+ // set test service
+ runShellCommand("device_config put textclassifier textclassifier_service_package_override "
+ + CtsTextClassifierService.MY_PACKAGE);
+ }
+
+ private CtsTextClassifierService waitServiceLazyConnect() throws InterruptedException {
+ return mServiceWatcher.waitOnConnected();
+ }
+
+ private void resetService() throws InterruptedException {
+ resetOriginalService();
+ if (mServiceWatcher.mService != null) {
+ mServiceWatcher.waitOnDisconnected();
+ }
+ CtsTextClassifierService.clearServiceWatcher();
+ mServiceWatcher = null;
+ }
+
+ private void resetOriginalService() {
+ Log.d(TAG, "reset to " + mOriginalOverrideService);
+ runShellCommand(
+ "device_config put textclassifier textclassifier_service_package_override "
+ + mOriginalOverrideService);
+ }
+
+ @Test
+ public void testOutsideOfPackageActivity_noRequestReceived() throws Exception {
+ // Start an Activity from another package to trigger a TextClassifier call
+ runQueryTextClassifierServiceActivity();
+
+ waitForIdle();
+
+ final Intent intent = mFinishReceiver.awaitForBroadcast();
+ assertThat(intent).isNotNull();
+
+ // We only bind to TextClassifierService when we are serving the first request.
+ // Wait service connected
+ final CtsTextClassifierService service = waitServiceLazyConnect();
+
+ // Wait a delay for the query is delivered.
+ service.awaitQuery(1_000);
+
+ // Verify the request can not pass to service
+ assertThat(service.getRequestSessions()).isEmpty();
+ }
+
+ private static void waitForIdle() {
+ UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ .waitForIdle();
+ }
+
+ private void runQueryTextClassifierServiceActivity() {
+ final String actionQuetyActivityFinish =
+ "ACTION_QUERY_SERVICE_ACTIVITY_FINISH_" + SystemClock.uptimeMillis();
+ final Context context = InstrumentationRegistry.getTargetContext();
+
+ mFinishReceiver = new BlockingBroadcastReceiver(context, actionQuetyActivityFinish);
+ mFinishReceiver.register();
+
+ final Intent outsideActivity = new Intent();
+ outsideActivity.setComponent(new ComponentName("android.textclassifier.cts2",
+ "android.textclassifier.cts2.QueryTextClassifierServiceActivity"));
+ outsideActivity.setFlags(FLAG_ACTIVITY_NEW_TASK);
+ final Intent broadcastIntent = new Intent(actionQuetyActivityFinish);
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, broadcastIntent,
+ 0);
+ outsideActivity.putExtra("finishBroadcast", pendingIntent);
+
+ context.startActivity(outsideActivity);
+ }
+}