Merge "Don't run AR tests in instant mode" into sc-dev
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 9ed0b6f..f216cf4 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -3855,6 +3855,7 @@
<action android:name="android.intent.action.MAIN" />
<action android:name="com.android.cts.verifier.managedprovisioning.action.CHECK_DEVICE_OWNER" />
<action android:name="com.android.cts.verifier.managedprovisioning.action.CHECK_PROFILE_OWNER" />
+ <action android:name="com.android.cts.verifier.managedprovisioning.action.CHECK_USER_AFFILIATED" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 51a1287..9dffc50 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -3479,8 +3479,10 @@
<string name="remove_device_owner_button">Remove device owner</string>
<string name="device_owner_check_device_owner_test">Check device owner</string>
<string name="device_owner_check_profile_owner_test">Check profile owner</string>
+ <string name="device_owner_check_user_affiliation_test">Check user affiliation</string>
<string name="device_owner_incorrect_device_owner">Missing or incorrect device owner: CTSVerifier is not DO for user %1$d!</string>
<string name="device_owner_incorrect_profile_owner">Missing or incorrect profile owner: CTSVerifier is not PO for user %1$d!</string>
+ <string name="device_owner_user_not_affiliated">User %1$d! is not affiliated</string>
<string name="device_owner_wifi_lockdown_test">WiFi configuration lockdown</string>
<string name="device_owner_wifi_lockdown_info">
Please enter the SSID and auth method of an available WiFi Access Point and press the button to create a
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index 0044e5c..00ae3b5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -53,10 +53,14 @@
"com.android.cts.verifier.managedprovisioning.action.CHECK_DEVICE_OWNER";
private static final String ACTION_CHECK_PROFILE_OWNER =
"com.android.cts.verifier.managedprovisioning.action.CHECK_PROFILE_OWNER";
+ private static final String ACTION_CHECK_CURRENT_USER_AFFILIATED =
+ "com.android.cts.verifier.managedprovisioning.action.CHECK_USER_AFFILIATED";
+
static final String EXTRA_TEST_ID = "extra-test-id";
private static final String CHECK_DEVICE_OWNER_TEST_ID = "CHECK_DEVICE_OWNER";
private static final String CHECK_PROFILE_OWNER_TEST_ID = "CHECK_PROFILE_OWNER";
+ private static final String CHECK_USER_AFFILIATED_TEST_ID = "CHECK_USER_AFFILIATED";
private static final String DEVICE_ADMIN_SETTINGS_ID = "DEVICE_ADMIN_SETTINGS";
private static final String WIFI_LOCKDOWN_TEST_ID = WifiLockdownTestActivity.class.getName();
private static final String DISABLE_STATUS_BAR_TEST_ID = "DISABLE_STATUS_BAR";
@@ -119,6 +123,18 @@
finish();
return;
}
+ if (ACTION_CHECK_CURRENT_USER_AFFILIATED.equals(getIntent().getAction())) {
+ DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
+ if (dpm.isAffiliatedUser()) {
+ TestResult.setPassedResult(this, getIntent().getStringExtra(EXTRA_TEST_ID),
+ null, null);
+ } else {
+ TestResult.setFailedResult(this, getIntent().getStringExtra(EXTRA_TEST_ID),
+ getString(R.string.device_owner_user_not_affiliated, getUserId()), null);
+ }
+ finish();
+ return;
+ }
setContentView(R.layout.positive_device_owner);
setInfoResources(R.string.device_owner_positive_tests,
@@ -169,6 +185,7 @@
switch(action) {
case ACTION_CHECK_DEVICE_OWNER:
case ACTION_CHECK_PROFILE_OWNER:
+ case ACTION_CHECK_CURRENT_USER_AFFILIATED:
// If this activity was started for checking device / profile owner status, then no
// need to do any tear down.
Log.d(TAG, "NOT starting createTearDownIntent() due to " + action);
@@ -193,6 +210,10 @@
R.string.device_owner_check_profile_owner_test,
new Intent(ACTION_CHECK_PROFILE_OWNER)
.putExtra(EXTRA_TEST_ID, getIntent().getStringExtra(EXTRA_TEST_ID))));
+ adapter.add(createTestItem(this, CHECK_USER_AFFILIATED_TEST_ID,
+ R.string.device_owner_check_user_affiliation_test,
+ new Intent(ACTION_CHECK_CURRENT_USER_AFFILIATED)
+ .putExtra(EXTRA_TEST_ID, getIntent().getStringExtra(EXTRA_TEST_ID))));
}
// device admin settings
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DeviceOwnerHelper.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DeviceOwnerHelper.java
index ed99c17..6989bab 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DeviceOwnerHelper.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DeviceOwnerHelper.java
@@ -68,7 +68,10 @@
String action = intent.getAction();
Log.d(TAG, "runManagerMethod(): user=" + context.getUserId() + ", action=" + action);
- if (!action.equals(ACTION_WRAPPED_MANAGER_CALL)) return false;
+ if (!action.equals(ACTION_WRAPPED_MANAGER_CALL)) {
+ if (VERBOSE) Log.v(TAG, "ignoring, it's not " + ACTION_WRAPPED_MANAGER_CALL);
+ return false;
+ }
try {
String className = intent.getStringExtra(EXTRA_CLASS);
@@ -86,9 +89,8 @@
for (int i = 0; i < numberArgs; i++) {
getArg(extras, args, parameterTypes, i);
}
- Log.d(TAG, "runManagerMethod(): args=" + Arrays.toString(args) + ", types="
- + Arrays.toString(parameterTypes));
-
+ Log.d(TAG, "converted args: " + Arrays.toString(args) + " (with types "
+ + Arrays.toString(parameterTypes) + ")");
} else {
args = null;
}
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DevicePolicyManagerWrapper.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DevicePolicyManagerWrapper.java
index 377439e..634364e 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DevicePolicyManagerWrapper.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DevicePolicyManagerWrapper.java
@@ -177,6 +177,38 @@
doAnswer(answer).when(spy).getGlobalPrivateDnsMode(any());
doAnswer(answer).when(spy).setGlobalPrivateDnsModeSpecifiedHost(any(), any());
+ // Used by StorageEncryptionTest
+ doAnswer(answer).when(spy).getStorageEncryptionStatus();
+ doAnswer(answer).when(spy).setStorageEncryption(any(), anyBoolean());
+
+ // Used by AdminConfiguredNetworksTest
+ doAnswer(answer).when(spy).setConfiguredNetworksLockdownState(any(), anyBoolean());
+
+ // Used by SecurityLoggingTest
+ doAnswer(answer).when(spy).isSecurityLoggingEnabled(any());
+ doAnswer(answer).when(spy).setDelegatedScopes(any(), any(), any());
+ doAnswer(answer).when(spy).retrieveSecurityLogs(any());
+
+ // Used by TimeManagementTest
+ doAnswer(answer).when(spy).setAutoTimeZoneEnabled(any(), anyBoolean());
+ doAnswer(answer).when(spy).setAutoTimeEnabled(any(), anyBoolean());
+ doAnswer(answer).when(spy).getAutoTimeZoneEnabled(any());
+
+ // Used by WifiTest
+ doAnswer(answer).when(spy).getWifiMacAddress(any());
+
+ // Used by AdminConfiguredNetworksTest
+ doAnswer(answer).when(spy).hasLockdownAdminConfiguredNetworks(any());
+
+ // Used by DevicePolicyLoggingTest
+ doAnswer(answer).when(spy).getAutoTimeEnabled(any());
+
+ // Used by InstallUpdateTest
+ doAnswer(answer).when(spy).installSystemUpdate(any(), any(), any(), any());
+
+ // Used by FactoryResetProtectionPolicyTest
+ doAnswer(answer).when(spy).getFactoryResetProtectionPolicy(any());
+
// TODO(b/176993670): add more methods below as tests are converted
} catch (Exception e) {
// Should never happen, but needs to be catch as some methods declare checked exceptions
diff --git a/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/BaseDeviceAdminTest.java b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/BaseDeviceAdminTest.java
index 454f7bf..bd0cdbd 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/BaseDeviceAdminTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/BaseDeviceAdminTest.java
@@ -23,12 +23,10 @@
import android.test.AndroidTestCase;
import android.util.Log;
-import com.android.bedstead.dpmwrapper.TestAppSystemServiceFactory;
-
public class BaseDeviceAdminTest extends AndroidTestCase {
private static final String TAG = BaseDeviceAdminTest.class.getSimpleName();
- public static class AdminReceiver extends DeviceAdminReceiver {
+ public static final class AdminReceiver extends DeviceAdminReceiver {
}
protected String mPackageName;
@@ -41,13 +39,15 @@
protected void setUp() throws Exception {
super.setUp();
- dpm = TestAppSystemServiceFactory.getDevicePolicyManager(mContext, AdminReceiver.class);
+ dpm = getContext().getSystemService(DevicePolicyManager.class);
int userId = mContext.getUserId();
mAdminComponent = new ComponentName(mContext, AdminReceiver.class);
mHasSecureLockScreen = mContext.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN);
- Log.d(TAG, "setUp(): userId=" + userId + ", admin=" + mAdminComponent);
+ Log.d(TAG, "setUp(): userId=" + userId + ", admin=" + mAdminComponent
+ + ", isDO=" + dpm.isDeviceOwnerApp(mContext.getPackageName())
+ + ", isPO=" + dpm.isProfileOwnerApp(mContext.getPackageName()));
}
/**
diff --git a/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/WipeDataTest.java b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/WipeDataTest.java
index ea010f4..003081e 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/WipeDataTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/WipeDataTest.java
@@ -15,15 +15,21 @@
*/
package com.android.cts.deviceadmin;
-public class WipeDataTest extends BaseDeviceAdminTest {
+import android.util.Log;
+
+public final class WipeDataTest extends BaseDeviceAdminTest {
+
+ private static final String TAG = WipeDataTest.class.getSimpleName();
// Caution: this test will wipe the device's data if it fails
public void testWipeDataThrowsSecurityException() {
try {
- dpm.wipeData(0);
+ Log.i(TAG, "Calling wipeData() on " + dpm);
+ dpm.wipeData(/* flags= */ 0);
fail("wipeData didn't throw expected SecurityException. Managed to kick off factory"
+ " reset process");
} catch (SecurityException expected) {
+ Log.v(TAG, "Got exception as expected: " + expected);
}
}
}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java
index 5637912..706a9c4 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java
@@ -18,18 +18,19 @@
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Process;
import android.util.Log;
+import com.android.bedstead.dpmwrapper.TestAppSystemServiceFactory;
+
/**
* Simple activity that adds or clears a user restriction depending on the value of the extras.
*/
-public class SetPolicyActivity extends Activity {
+public final class SetPolicyActivity extends Activity {
- private static final String TAG = SetPolicyActivity.class.getName();
+ private static final String TAG = SetPolicyActivity.class.getSimpleName();
private static final String EXTRA_RESTRICTION_KEY = "extra-restriction-key";
private static final String EXTRA_COMMAND = "extra-command";
@@ -51,10 +52,10 @@
}
private void handleIntent(Intent intent) {
- DevicePolicyManager dpm = (DevicePolicyManager)
- getSystemService(Context.DEVICE_POLICY_SERVICE);
+ DevicePolicyManager dpm = TestAppSystemServiceFactory.getDevicePolicyManager(this,
+ BasicAdminReceiver.class);
String command = intent.getStringExtra(EXTRA_COMMAND);
- Log.i(TAG, "Command: \"" + command);
+ Log.i(TAG, "Command: \"" + command + " DPM: " + dpm);
ComponentName admin = BasicAdminReceiver.getComponentName(this);
if (ADD_RESTRICTION_COMMAND.equals(command)) {
String restrictionKey = intent.getStringExtra(EXTRA_RESTRICTION_KEY);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 9e852a5..41ed185 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -1199,15 +1199,18 @@
// (DPMS.manageUserUnchecked(), which don't grant it (as this is a privileged permission
// that's not available to 3rd party apps). If we get rid of DevicePolicyManagerWrapper,
// we won't need to grant it anymore.
- CLog.i("Granting INTERACT_ACROSS_USERS to DO %s on user %d as it will need to send ordered "
- + "broadcasts to user 0", deviceAdminPkg, userId);
+ CLog.i("Granting INTERACT_ACROSS_USERS package (%s) on user %d as its PO will need to "
+ + "send ordered broadcasts to user 0", deviceAdminPkg, userId);
executeShellCommand("pm grant --user %d %s android.permission.INTERACT_ACROSS_USERS",
userId, deviceAdminPkg);
- CLog.i("Granting WRITE_SECURE_SETTINGS package (%s) on user %d as some tests might need it",
- deviceAdminPkg, userId);
+ CLog.i("Granting WRITE_SECURE_SETTINGS to admin package (%s) on user %d as some tests need "
+ + "it", deviceAdminPkg, userId);
executeShellCommand("pm grant --user %d %s android.permission.WRITE_SECURE_SETTINGS",
userId, deviceAdminPkg);
+
+ CLog.i("Granting ALLOW_TEST_API_ACCESS to package %s", deviceAdminPkg);
+ executeShellCommand("am compat enable ALLOW_TEST_API_ACCESS %s", deviceAdminPkg);
}
/** Find effective restriction for user */
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 60a397e..0851291 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -581,20 +581,25 @@
@Test
public void testDisallowFactoryReset() throws Exception {
int adminVersion = 24;
- changeUserRestrictionOrFail("no_factory_reset", true, mPrimaryUserId,
- DEVICE_OWNER_PKG);
+ // NOTE: the restriction must be set on primary user as it will launch SetPolicyActivity,
+ // but the admin must be installed on USER_SYSTEM, otherwise wipeData() on headless system
+ // user mode would wipe the current user (instead of factory resetting the device)
+ changeUserRestrictionOrFail("no_factory_reset", true, mPrimaryUserId, DEVICE_OWNER_PKG);
+ int adminUserId = USER_SYSTEM;
+
+ String deviceAdminPkg = DeviceAdminHelper.getDeviceAdminApkPackage(adminVersion);
+ String deviceAdminReceiver = DeviceAdminHelper.getAdminReceiverComponent(adminVersion);
try {
installAppAsUser(DeviceAdminHelper.getDeviceAdminApkFileName(adminVersion),
- mPrimaryUserId);
- setDeviceAdmin(DeviceAdminHelper.getAdminReceiverComponent(adminVersion),
- mPrimaryUserId);
+ adminUserId);
+ setDeviceAdmin(deviceAdminReceiver, adminUserId);
runDeviceTestsAsUser(
- DeviceAdminHelper.getDeviceAdminApkPackage(adminVersion),
+ deviceAdminPkg,
DeviceAdminHelper.getDeviceAdminJavaPackage() + ".WipeDataTest",
- "testWipeDataThrowsSecurityException", mPrimaryUserId);
+ "testWipeDataThrowsSecurityException", adminUserId);
} finally {
- removeAdmin(DeviceAdminHelper.getAdminReceiverComponent(adminVersion), mPrimaryUserId);
- getDevice().uninstallPackage(DeviceAdminHelper.getDeviceAdminApkPackage(adminVersion));
+ removeAdmin(deviceAdminReceiver, adminUserId);
+ getDevice().uninstallPackage(deviceAdminPkg);
}
}
@@ -609,7 +614,8 @@
@Test
public void testDeviceOwnerCanGetDeviceIdentifiers() throws Exception {
// The Device Owner should have access to all device identifiers.
- executeDeviceTestMethod(".DeviceIdentifiersTest",
+
+ executeDeviceOwnerTestMethod(".DeviceIdentifiersTest",
"testDeviceOwnerCanGetDeviceIdentifiersWithPermission");
}
@@ -624,7 +630,6 @@
// Install the package in primary user
runDeviceTestsAsUser(DEVICE_OWNER_PKG, ".PackageInstallTest",
"testPackageInstall", mPrimaryUserId);
-
assertMetricsLogged(getDevice(), () -> {
runDeviceTestsAsUser(DEVICE_OWNER_PKG, ".PackageInstallTest",
"testKeepPackageCache", mPrimaryUserId);
@@ -926,7 +931,7 @@
installAppAsUser(DEVICE_OWNER_APK, userId);
setProfileOwnerOrFail(DEVICE_OWNER_COMPONENT, userId);
} else {
- grantDpmWrapperPermissions(DEVICE_OWNER_APK, userId);
+ grantDpmWrapperPermissions(DEVICE_OWNER_PKG, userId);
}
wakeupAndDismissKeyguard();
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
index d370b3f..ba2eda4 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.FlakyTest;
import android.platform.test.annotations.LargeTest;
@@ -112,4 +113,11 @@
// Profile owner cannot set auto time zone unless it is called by the profile
// owner of an organization-owned managed profile or a profile owner on user 0.
}
+
+ @Override
+ @Test
+ public void testSetAutoTimeEnabled() {
+ // This test should be skipped when profile owner is set on secondary user.
+ assumeTrue("Skipping test: profile owner is not on system user", mUserId == USER_SYSTEM);
+ }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
index 55acbda..56016cd 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
@@ -16,19 +16,24 @@
package android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.app.Activity;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.server.wm.WindowManagerTestBase.FocusableActivity;
import android.server.wm.app.AbstractLifecycleLogActivity;
import androidx.test.filters.FlakyTest;
@@ -52,7 +57,7 @@
* The behavior without enabling a compatibility change is also tested as a baseline.
*
* <p>Build/Install/Run:
- * atest CtsWindowManagerDeviceTestCases:CompatChangeTests
+ * atest CtsWindowManagerDeviceTestCases:CompatChangeTests
*/
@Presubmit
@FlakyTest(bugId = 182185145)
@@ -140,12 +145,77 @@
SUPPORTS_SIZE_CHANGES_PORTRAIT_ACTIVITY, /* inSizeCompatModeAfterResize= */ true);
}
+ /**
+ * Test that a min aspect ratio activity in letterbox results in sandboxed Display APIs.
+ */
+ @Test
+ public void testSandboxForNonResizablePortraitActivity() {
+ runSandboxTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /* isSandboxed= */ true);
+ }
+
+ /**
+ * Test that a min aspect ratio activity in letterbox does not have the Display APIs sandboxed
+ * when the {@link ActivityInfo#NEVER_SANDBOX_DISPLAY_APIS} compat change is enabled.
+ */
+ @Test
+ @EnableCompatChanges({ActivityInfo.NEVER_SANDBOX_DISPLAY_APIS})
+ public void testSandboxForNonResizablePortraitActivityNeverSandboxDisplayApisEnabled() {
+ runSandboxTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /* isSandboxed= */ false);
+ }
+
+ /**
+ * Test that a min aspect ratio activity in letterbox does have the Display APIs sandboxed
+ * when the {@link ActivityInfo#ALWAYS_SANDBOX_DISPLAY_APIS} compat change is enabled.
+ */
+ @Test
+ @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
+ public void testSandboxForNonResizablePortraitActivityAlwaysSandboxDisplayApisEnabled() {
+ runSandboxTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /* isSandboxed= */ true);
+ }
+
+ /**
+ * Test that a resizable portrait activity in split screen does have the Display APIs sandboxed
+ * when the {@link ActivityInfo#ALWAYS_SANDBOX_DISPLAY_APIS} compat change is enabled.
+ */
+ @Test
+ @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
+ public void testSandboxForResizablePortraitActivityAlwaysSandboxDisplayApisEnabled() {
+ assumeTrue("Skipping test: no split multi-window support",
+ supportsSplitScreenMultiWindow());
+
+ // Launch a resizable activity into split screen.
+ launchActivityOnDisplay(RESIZEABLE_PORTRAIT_ACTIVITY, DEFAULT_DISPLAY);
+ putActivityInPrimarySplit(RESIZEABLE_PORTRAIT_ACTIVITY);
+ mWmState.computeState(RESIZEABLE_PORTRAIT_ACTIVITY);
+
+ // The resizable activity is sandboxed, due to the config being enabled.
+ assertSandboxed(RESIZEABLE_PORTRAIT_ACTIVITY, /* expectedSandboxed= */ true);
+ }
+
+ /**
+ * Launches the provided activity into size compat mode twice. The first time, the display
+ * is resized to be half the size. The second time, the display is resized to be twice the
+ * original size.
+ *
+ * @param activity the activity under test.
+ * @param inSizeCompatModeAfterResize if the activity should be in size compat mode after
+ * resizing the display
+ */
private void runSizeCompatTest(ComponentName activity, boolean inSizeCompatModeAfterResize) {
runSizeCompatTest(activity, /* resizeRatio= */ 0.5, inSizeCompatModeAfterResize);
mDisplayMetricsSession.restoreDisplayMetrics();
runSizeCompatTest(activity, /* resizeRatio= */ 2, inSizeCompatModeAfterResize);
}
+ /**
+ * Launches the provided activity on the default display, initially not in size compat mode.
+ * After resizing the display, verifies if activity is in size compat mode or not
+ *
+ * @param activity the activity under test
+ * @param resizeRatio the ratio to resize the display
+ * @param inSizeCompatModeAfterResize if the activity should be in size compat mode after
+ * resizing the display
+ */
private void runSizeCompatTest(ComponentName activity, double resizeRatio,
boolean inSizeCompatModeAfterResize) {
launchActivityOnDisplay(activity, DEFAULT_DISPLAY);
@@ -161,14 +231,49 @@
WindowManagerState.Activity activityContainer = mWmState.getActivity(activity);
assertNotNull(activityContainer);
if (expectedInSizeCompatMode) {
- assertTrue("The Window should be in size compat mode",
+ assertTrue("The Window must be in size compat mode",
activityContainer.inSizeCompatMode());
} else {
- assertFalse("The Window should not be in size compat mode",
+ assertFalse("The Window must not be in size compat mode",
activityContainer.inSizeCompatMode());
}
}
+ /**
+ * Similar to {@link #runSizeCompatTest(ComponentName, boolean)}, but the activity is expected
+ * to be in size compat mode after resizing the display.
+ *
+ * @param activity the activity under test
+ * @param isSandboxed when {@code true}, {@link android.app.WindowConfiguration#getMaxBounds()}
+ * are sandboxed to the activity bounds. Otherwise, they inherit the
+ * DisplayArea bounds
+ */
+ private void runSandboxTest(ComponentName activity, boolean isSandboxed) {
+ runSizeCompatTest(activity, /* resizeRatio= */ 0.5, /* inSizeCompatModeAfterResize=*/ true);
+ assertSandboxed(activity, isSandboxed);
+ mDisplayMetricsSession.restoreDisplayMetrics();
+ runSizeCompatTest(activity, /* resizeRatio= */ 2, /* inSizeCompatModeAfterResize=*/ true);
+ assertSandboxed(activity, isSandboxed);
+ }
+
+ private void assertSandboxed(ComponentName activity, boolean expectedSandboxed) {
+ mWmState.computeState(new WaitForValidActivityState(activity));
+ final WindowManagerState.ActivityTask activityTask = mWmState.getTaskByActivity(activity);
+ assertNotNull(activityTask);
+ final Rect activityBounds = activityTask.getBounds();
+ final Rect maxBounds = activityTask.mFullConfiguration.windowConfiguration.getMaxBounds();
+ WindowManagerState.DisplayArea tda = mWmState.getTaskDisplayArea(activity);
+ if (expectedSandboxed) {
+ assertEquals(
+ "The Window has max bounds sandboxed to the window bounds",
+ activityBounds, maxBounds);
+ } else if (tda != null) {
+ assertEquals(
+ "The Window is not sandboxed, with max bounds reflecting the DisplayArea",
+ tda.mFullConfiguration.windowConfiguration.getBounds(), maxBounds);
+ }
+ }
+
private void resizeDisplay(ComponentName activity, double sizeRatio) {
mDisplayMetricsSession.changeDisplayMetrics(sizeRatio, /* densityRatio= */ 1);
mWmState.computeState(new WaitForValidActivityState(activity));
@@ -178,7 +283,7 @@
return new ComponentName(getInstrumentation().getContext(), activity);
}
- public static class ResizeablePortraitActivity extends AbstractLifecycleLogActivity {
+ public static class ResizeablePortraitActivity extends FocusableActivity {
}
public static class NonResizeablePortraitActivity extends AbstractLifecycleLogActivity {
diff --git a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
index 7adc3e3..a3c46d5 100644
--- a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
+++ b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
@@ -27,6 +27,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.function.Predicate;
/**
* Checks that parts of the device's API that are annotated (e.g. with android.annotation.SystemApi)
@@ -45,6 +46,15 @@
mAnnotationForExactMatch = instrumentationArgs.getString("annotation-for-exact-match");
}
+ private Predicate<? super JDiffClassDescription> androidAutoClassesFilter() {
+ if (getInstrumentation().getContext().getPackageManager().hasSystemFeature(
+ "android.hardware.type.automotive")) {
+ return clz -> true;
+ } else {
+ return clz -> !clz.getAbsoluteClassName().startsWith("android.car.");
+ }
+ }
+
/**
* Tests that the parts of the device's API that are annotated (e.g. with
* android.annotation.SystemApi) match the API definition.
@@ -81,6 +91,7 @@
ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
parseApiResourcesAsStream(apiDocumentParser, mExpectedApiFiles)
+ .filter(androidAutoClassesFilter())
.forEach(complianceChecker::checkSignatureCompliance);
// After done parsing all expected API files, perform any deferred checks.
diff --git a/tests/signature/lib/common/src/android/signature/cts/AnnotationChecker.java b/tests/signature/lib/common/src/android/signature/cts/AnnotationChecker.java
index 3f14dad..1567f16 100644
--- a/tests/signature/lib/common/src/android/signature/cts/AnnotationChecker.java
+++ b/tests/signature/lib/common/src/android/signature/cts/AnnotationChecker.java
@@ -27,7 +27,7 @@
/**
* Checks that the runtime representation of a class matches the API representation of a class.
*/
-public class AnnotationChecker extends AbstractApiChecker {
+public class AnnotationChecker extends ApiPresenceChecker {
private final String annotationSpec;
@@ -39,7 +39,7 @@
private final Map<String, Set<Field>> annotatedFieldsMap = new HashMap<>();
/**
- * @param annotationName name of the annotation class for the API type (e.g.
+ * @param annotationSpec name of the annotation class for the API type (e.g.
* android.annotation.SystemApi)
*/
public AnnotationChecker(
@@ -82,7 +82,6 @@
public boolean skip(Field f);
}
- @Override
public void checkDeferred() {
for (Class<?> clazz : annotatedClassesMap.values()) {
if (filter != null && filter.skip(clazz)) continue;
@@ -117,17 +116,6 @@
}
@Override
- protected boolean allowMissingClass(JDiffClassDescription classDescription) {
- // A class that exist in the API document is not found in the runtime.
- // This can happen for classes that are optional (e.g. classes for
- // Android Auto). This, however, should not be considered as a test
- // failure, because the purpose of this test is to ensure that every
- // runtime classes found in the device have more annotations than
- // the documented.
- return true;
- }
-
- @Override
protected boolean checkClass(JDiffClassDescription classDescription, Class<?> runtimeClass) {
// remove the class from the set if found
annotatedClassesMap.remove(runtimeClass.getName());
diff --git a/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java b/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java
index f1c812e..fe67157 100644
--- a/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java
+++ b/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java
@@ -29,7 +29,7 @@
/**
* Checks that the runtime representation of a class matches the API representation of a class.
*/
-public class ApiComplianceChecker extends AbstractApiChecker {
+public class ApiComplianceChecker extends ApiPresenceChecker {
/**
* A set of method signatures whose abstract modifier should be ignored.
@@ -73,7 +73,6 @@
interfaceChecker = new InterfaceChecker(resultObserver, classProvider);
}
- @Override
public void checkDeferred() {
interfaceChecker.checkQueued();
}
diff --git a/tests/signature/lib/common/src/android/signature/cts/AbstractApiChecker.java b/tests/signature/lib/common/src/android/signature/cts/ApiPresenceChecker.java
similarity index 86%
rename from tests/signature/lib/common/src/android/signature/cts/AbstractApiChecker.java
rename to tests/signature/lib/common/src/android/signature/cts/ApiPresenceChecker.java
index 03c4a85..fc4335c 100644
--- a/tests/signature/lib/common/src/android/signature/cts/AbstractApiChecker.java
+++ b/tests/signature/lib/common/src/android/signature/cts/ApiPresenceChecker.java
@@ -27,13 +27,13 @@
* Base class for those that process a set of API definition files and perform some checking on
* them.
*/
-public abstract class AbstractApiChecker {
+public class ApiPresenceChecker {
final ResultObserver resultObserver;
final ClassProvider classProvider;
- AbstractApiChecker(ClassProvider classProvider, ResultObserver resultObserver) {
+ public ApiPresenceChecker(ClassProvider classProvider, ResultObserver resultObserver) {
this.classProvider = classProvider;
this.resultObserver = resultObserver;
}
@@ -63,14 +63,10 @@
.findRequiredClass(classDescription, classProvider);
if (runtimeClass == null) {
- // No class found, notify the observer according to the class type,
- // if missing a class isn't acceptable.
- if (!allowMissingClass(classDescription)) {
- resultObserver.notifyFailure(FailureType.missing(classDescription),
- classDescription.getAbsoluteClassName(),
- "Classloader is unable to find " + classDescription
- .getAbsoluteClassName());
- }
+ resultObserver.notifyFailure(FailureType.missing(classDescription),
+ classDescription.getAbsoluteClassName(),
+ "Classloader is unable to find " + classDescription
+ .getAbsoluteClassName());
return null;
}
@@ -90,11 +86,6 @@
}
/**
- * Perform any additional checks that can only be done after all api files have been processed.
- */
- public abstract void checkDeferred();
-
- /**
* Implement to provide custom check of the supplied class description.
*
* <p>This should not peform checks on the members, those will be done separately depending
@@ -104,21 +95,12 @@
* @param runtimeClass the runtime class corresponding to the class description.
* @return true if the checks passed and the members should now be checked.
*/
- protected abstract boolean checkClass(JDiffClassDescription classDescription,
- Class<?> runtimeClass);
-
-
- /**
- * Checks that a class that exists in the API xml file but that does not exist
- * in the runtime is allowed or not.
- *
- * @param classDescription the class description that is missing.
- * @return true if missing the class is acceptable.
- */
- protected boolean allowMissingClass(JDiffClassDescription classDescription) {
- return false;
+ protected boolean checkClass(JDiffClassDescription classDescription,
+ Class<?> runtimeClass) {
+ return true;
}
+
/**
* Checks all fields in test class for compliance with the API xml.
*
@@ -175,9 +157,10 @@
return fieldMap;
}
- protected abstract void checkField(JDiffClassDescription classDescription,
+ protected void checkField(JDiffClassDescription classDescription,
Class<?> runtimeClass,
- JDiffClassDescription.JDiffField fieldDescription, Field field);
+ JDiffClassDescription.JDiffField fieldDescription, Field field) {
+ }
/**
@@ -217,9 +200,10 @@
}
}
- protected abstract void checkConstructor(JDiffClassDescription classDescription,
+ protected void checkConstructor(JDiffClassDescription classDescription,
Class<?> runtimeClass,
- JDiffClassDescription.JDiffConstructor ctorDescription, Constructor<?> ctor);
+ JDiffClassDescription.JDiffConstructor ctorDescription, Constructor<?> ctor) {
+ }
/**
* Checks that the method found through reflection matches the
@@ -260,7 +244,8 @@
}
}
- protected abstract void checkMethod(JDiffClassDescription classDescription,
+ protected void checkMethod(JDiffClassDescription classDescription,
Class<?> runtimeClass,
- JDiffClassDescription.JDiffMethod methodDescription, Method method);
+ JDiffClassDescription.JDiffMethod methodDescription, Method method) {
+ }
}
diff --git a/tests/signature/tests/src/android/signature/cts/tests/AnnotationCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/AnnotationCheckerTest.java
index a981be7..3e18522 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/AnnotationCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/AnnotationCheckerTest.java
@@ -21,8 +21,9 @@
import android.signature.cts.FailureType;
import android.signature.cts.JDiffClassDescription;
import android.signature.cts.ResultObserver;
-import android.signature.cts.tests.data.ApiAnnotation;
+
import java.lang.reflect.Modifier;
+import java.util.function.Consumer;
import org.junit.Test;
import org.junit.runners.JUnit4;
@@ -32,7 +33,7 @@
* Test class for {@link android.signature.cts.AnnotationChecker}.
*/
@RunWith(JUnit4.class)
-public class AnnotationCheckerTest extends AbstractApiCheckerTest<AnnotationChecker> {
+public class AnnotationCheckerTest extends ApiPresenceCheckerTest<AnnotationChecker> {
@Override
protected AnnotationChecker createChecker(ResultObserver resultObserver,
@@ -41,6 +42,18 @@
"@android.signature.cts.tests.data.ApiAnnotation()", null);
}
+ @Override
+ void runWithApiChecker(ResultObserver resultObserver, Consumer<AnnotationChecker> consumer,
+ String... excludedRuntimeClasses) {
+ super.runWithApiChecker(
+ resultObserver,
+ checker -> {
+ consumer.accept(checker);
+ checker.checkDeferred();
+ },
+ excludedRuntimeClasses);
+ }
+
private static void addConstructor(JDiffClassDescription clz, String... paramTypes) {
JDiffClassDescription.JDiffConstructor constructor = new JDiffClassDescription.JDiffConstructor(
clz.getShortClassName(), Modifier.PUBLIC);
diff --git a/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
index 405f5b2..c4c87f5 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
+import android.signature.cts.AnnotationChecker;
import android.signature.cts.ApiComplianceChecker;
import android.signature.cts.ClassProvider;
import android.signature.cts.FailureType;
@@ -28,8 +29,8 @@
import android.signature.cts.tests.data.NormalClass;
import android.signature.cts.tests.data.NormalInterface;
import java.lang.reflect.Modifier;
+import java.util.function.Consumer;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runners.JUnit4;
import org.junit.runner.RunWith;
@@ -38,7 +39,7 @@
* Test class for JDiffClassDescription.
*/
@RunWith(JUnit4.class)
-public class ApiComplianceCheckerTest extends AbstractApiCheckerTest<ApiComplianceChecker> {
+public class ApiComplianceCheckerTest extends ApiPresenceCheckerTest<ApiComplianceChecker> {
@Override
protected ApiComplianceChecker createChecker(ResultObserver resultObserver,
@@ -46,6 +47,18 @@
return new ApiComplianceChecker(resultObserver, provider);
}
+ @Override
+ void runWithApiChecker(
+ ResultObserver resultObserver, Consumer<ApiComplianceChecker> consumer, String... excludedRuntimeClasses) {
+ super.runWithApiChecker(
+ resultObserver,
+ checker -> {
+ consumer.accept(checker);
+ checker.checkDeferred();
+ },
+ excludedRuntimeClasses);
+ }
+
@Test
public void testNormalClassCompliance() {
JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
diff --git a/tests/signature/tests/src/android/signature/cts/tests/AbstractApiCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/ApiPresenceCheckerTest.java
similarity index 95%
rename from tests/signature/tests/src/android/signature/cts/tests/AbstractApiCheckerTest.java
rename to tests/signature/tests/src/android/signature/cts/tests/ApiPresenceCheckerTest.java
index 901b424..719be91 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/AbstractApiCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/ApiPresenceCheckerTest.java
@@ -15,7 +15,7 @@
*/
package android.signature.cts.tests;
-import android.signature.cts.AbstractApiChecker;
+import android.signature.cts.ApiPresenceChecker;
import android.signature.cts.ClassProvider;
import android.signature.cts.ExcludingClassProvider;
import android.signature.cts.FailureType;
@@ -28,9 +28,9 @@
import org.junit.Assert;
/**
- * Base class for tests of implementations of {@link AbstractApiChecker}.
+ * Base class for tests of implementations of {@link ApiPresenceChecker}.
*/
-public abstract class AbstractApiCheckerTest<T extends AbstractApiChecker> {
+public abstract class ApiPresenceCheckerTest<T extends ApiPresenceChecker> {
static final String VALUE = "VALUE";
@@ -79,7 +79,6 @@
ClassProvider provider = createClassProvider(excludedRuntimeClasses);
T checker = createChecker(resultObserver, provider);
consumer.accept(checker);
- checker.checkDeferred();
}
protected abstract T createChecker(ResultObserver resultObserver, ClassProvider provider);
diff --git a/tests/smartspace/src/android/smartspace/cts/SmartspaceManagerTest.java b/tests/smartspace/src/android/smartspace/cts/SmartspaceManagerTest.java
index 936a835..8177a99 100644
--- a/tests/smartspace/src/android/smartspace/cts/SmartspaceManagerTest.java
+++ b/tests/smartspace/src/android/smartspace/cts/SmartspaceManagerTest.java
@@ -101,7 +101,7 @@
@After
public void tearDown() throws Exception {
Log.d(TAG, "Starting tear down, watcher is: " + mWatcher);
- mClient.destroy();
+ mClient.close();
setService(null);
await(mWatcher.destroyed, "Waiting for onDestroy()");
@@ -118,7 +118,7 @@
@Test
public void testDestroySession() {
SmartspaceSession localClient = createSmartspaceSession(createSmartspaceConfig("surface"));
- localClient.destroy();
+ localClient.close();
await(mWatcher.destroyed, "Waiting for onDestroy()");
}
@@ -131,7 +131,7 @@
SmartspaceTargetEvent.EVENT_TARGET_INTERACTION).setSmartspaceTarget(
testTarget).setSmartspaceActionId("id").build();
mClient.notifySmartspaceEvent(testEvent);
- mClient.registerSmartspaceUpdates(Executors.newSingleThreadExecutor(),
+ mClient.addOnTargetsAvailableListener(Executors.newSingleThreadExecutor(),
targets -> {
if (targets.size() > 0 && targets.get(0).equals(testTarget)) {
mWatcher.queried.countDown();
@@ -156,14 +156,14 @@
SmartspaceSession client1 = createSmartspaceSession(config1);
SmartspaceConfig config2 = createSmartspaceConfig("surface 2");
SmartspaceSession client2 = createSmartspaceSession(config2);
- client1.registerSmartspaceUpdates(Executors.newSingleThreadExecutor(),
+ client1.addOnTargetsAvailableListener(Executors.newSingleThreadExecutor(),
targets -> {
// Counting down only if the returned list only contains test target.
if (targets.size() > 0 && targets.get(0).equals(testTarget)) {
mWatcher.queriedTwice.countDown();
}
});
- client2.registerSmartspaceUpdates(Executors.newSingleThreadExecutor(),
+ client2.addOnTargetsAvailableListener(Executors.newSingleThreadExecutor(),
targets -> {
// Counting down only if the returned list is empty.
if (targets.isEmpty()) {
@@ -267,7 +267,7 @@
}
}
- private static class RequestVerifier implements SmartspaceSession.Callback {
+ private static class RequestVerifier implements SmartspaceSession.OnTargetsAvailableListener {
@Override
public void onTargetsAvailable(List<SmartspaceTarget> targets) {
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionTest.java b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
index 8a51982..016c9ba 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
@@ -23,7 +23,7 @@
import static android.media.cts.MediaSessionTestService.STEP_CLEAN_UP;
import static android.media.cts.MediaSessionTestService.STEP_SET_UP;
import static android.media.cts.MediaSessionTestService.TEST_SERIES_OF_SET_QUEUE;
-import static android.media.cts.MediaSessionTestService.TEST_SET_QUEUE_WITH_LARGE_NUMBER_OF_ITEMS;
+import static android.media.cts.MediaSessionTestService.TEST_SET_QUEUE;
import static android.media.cts.Utils.compareRemoteUserInfo;
import android.app.PendingIntent;
@@ -54,6 +54,7 @@
import android.view.KeyEvent;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -941,7 +942,7 @@
}
try (RemoteService.Invoker invoker = new RemoteService.Invoker(mContext,
- MediaSessionTestService.class, TEST_SET_QUEUE_WITH_LARGE_NUMBER_OF_ITEMS)) {
+ MediaSessionTestService.class, TEST_SET_QUEUE)) {
Bundle args = new Bundle();
args.putParcelable(KEY_SESSION_TOKEN, mSession.getSessionToken());
args.putInt(KEY_EXPECTED_QUEUE_SIZE, queueSize);
@@ -952,6 +953,19 @@
}
}
+ public void testSetQueueWithEmptyQueue() throws Exception {
+ try (RemoteService.Invoker invoker = new RemoteService.Invoker(mContext,
+ MediaSessionTestService.class, TEST_SET_QUEUE)) {
+ Bundle args = new Bundle();
+ args.putParcelable(KEY_SESSION_TOKEN, mSession.getSessionToken());
+ args.putInt(KEY_EXPECTED_QUEUE_SIZE, 0);
+ invoker.run(STEP_SET_UP, args);
+ mSession.setQueue(Collections.emptyList());
+ invoker.run(STEP_CHECK);
+ invoker.run(STEP_CLEAN_UP);
+ }
+ }
+
/**
* Verifies that a new session hasn't had any configuration bits set yet.
*
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionTestService.java b/tests/tests/media/src/android/media/cts/MediaSessionTestService.java
index 1b82872..08476ba 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionTestService.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionTestService.java
@@ -33,7 +33,7 @@
public class MediaSessionTestService extends RemoteService {
public static final int TEST_SERIES_OF_SET_QUEUE = 0;
- public static final int TEST_SET_QUEUE_WITH_LARGE_NUMBER_OF_ITEMS = 1;
+ public static final int TEST_SET_QUEUE = 1;
public static final int STEP_SET_UP = 0;
public static final int STEP_CHECK = 1;
@@ -80,7 +80,7 @@
mAllItemsNotified = null;
}
- private void testSetQueueWithLargeNumberOfItems_setUp(Bundle args) {
+ private void testSetQueue_setUp(Bundle args) {
MediaSession.Token token = args.getParcelable(KEY_SESSION_TOKEN);
int expectedQueueSize = args.getInt(KEY_EXPECTED_QUEUE_SIZE);
@@ -98,11 +98,11 @@
new Handler(Looper.getMainLooper()));
}
- private void testSetQueueWithLargeNumberOfItems_check() throws Exception {
+ private void testSetQueue_check() throws Exception {
assertTrue(mQueueNotified.await(TIMEOUT_MS, MILLISECONDS));
}
- private void testSetQueueWithLargeNumberOfItems_cleanUp() {
+ private void testSetQueue_cleanUp() {
mMediaController.unregisterCallback(mMediaControllerCallback);
mMediaController = null;
mMediaControllerCallback = null;
@@ -121,13 +121,13 @@
} else {
throw new IllegalArgumentException("Unknown step=" + step);
}
- } else if (testId == TEST_SET_QUEUE_WITH_LARGE_NUMBER_OF_ITEMS) {
+ } else if (testId == TEST_SET_QUEUE) {
if (step == STEP_SET_UP) {
- testSetQueueWithLargeNumberOfItems_setUp(args);
+ testSetQueue_setUp(args);
} else if (step == STEP_CHECK) {
- testSetQueueWithLargeNumberOfItems_check();
+ testSetQueue_check();
} else if (step == STEP_CLEAN_UP) {
- testSetQueueWithLargeNumberOfItems_cleanUp();
+ testSetQueue_cleanUp();
} else {
throw new IllegalArgumentException("Unknown step=" + step);
}
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
index 0d4558ec0..3f71f46 100644
--- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -179,12 +179,12 @@
}
eventually {
if (useMic) {
- val appView = uiDevice.findObject(UiSelector().textContains(micLabel))
- assertTrue("View with text $APP_LABEL not found", appView.exists())
+ val iconView = uiDevice.findObject(UiSelector().descriptionContains(micLabel))
+ assertTrue("View with description $micLabel not found", iconView.exists())
}
if (useCamera) {
- val appView = uiDevice.findObject(UiSelector().textContains(cameraLabel))
- assertTrue("View with text $APP_LABEL not found", appView.exists())
+ val iconView = uiDevice.findObject(UiSelector().descriptionContains(cameraLabel))
+ assertTrue("View with text $APP_LABEL not found", iconView.exists())
}
val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
assertTrue("View with text $APP_LABEL not found", appView.exists())
diff --git a/tests/tests/permission5/Android.bp b/tests/tests/permission5/Android.bp
index 242f4d1..d7cb067 100644
--- a/tests/tests/permission5/Android.bp
+++ b/tests/tests/permission5/Android.bp
@@ -28,6 +28,7 @@
"compatibility-device-util-axt",
"truth-prebuilt",
"ctstestrunner-axt",
+ "platform-test-annotations",
],
data: [
":CtsBlamedPermissionApp",
diff --git a/tests/tests/permission5/src/android/permission5/cts/RenouncedPermissionsTest.kt b/tests/tests/permission5/src/android/permission5/cts/RenouncedPermissionsTest.kt
index 30d795e..98f73af 100644
--- a/tests/tests/permission5/src/android/permission5/cts/RenouncedPermissionsTest.kt
+++ b/tests/tests/permission5/src/android/permission5/cts/RenouncedPermissionsTest.kt
@@ -24,6 +24,7 @@
import android.content.pm.PackageManager
import android.os.Process
import android.permission.PermissionManager
+import android.platform.test.annotations.AppModeFull
import android.provider.CalendarContract
import android.provider.ContactsContract
import android.util.ArraySet
@@ -41,6 +42,7 @@
@Test
@Throws(Exception::class)
+ @AppModeFull(reason="Instant apps cannot hold READ_CALENDAR/READ_CONTACTS permissions")
fun testRenouncePermissionsChain() {
val receiverAttributionSource = getShellAttributionSourceWithRenouncedPermissions()
val activity = createActivityWithAttributionContext(receiverAttributionSource)
diff --git a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
index b5cfdcb..a0cd93e 100644
--- a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
+++ b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
@@ -29,6 +29,7 @@
import android.os.Process
import android.os.RemoteCallback
import android.os.SystemClock
+import android.platform.test.annotations.AppModeFull
import android.provider.CalendarContract
import android.provider.CallLog
import android.provider.ContactsContract
@@ -47,6 +48,7 @@
import java.util.concurrent.locks.ReentrantLock
import java.util.function.Consumer
+@AppModeFull(reason="Instant apps cannot hold READ_CONTACTS/READ_CALENDAR/READ_SMS/READ_CALL_LOG")
class RuntimePermissionsAppOpTrackingTest {
@Before
diff --git a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
index dd60884..4d8a54c 100644
--- a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
+++ b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
@@ -56,12 +56,15 @@
public static final int VOICE_INTERACTION_SERVICE_NORMAL_TEST = 0;
public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_TEST = 1;
public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_WITHOUT_PERMISSION_TEST = 2;
+ public static final int HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST = 3;
public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS = 1;
public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_ILLEGAL_STATE_EXCEPTION = 2;
public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_SECURITY_EXCEPTION = 3;
public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_SHARED_MEMORY_NOT_READ_ONLY = 4;
+ public static final int HOTWORD_DETECTION_SERVICE_ONDETECT_SUCCESS = 1;
+
public static final String TESTCASE_TYPE = "testcase_type";
public static final String TESTINFO = "testinfo";
public static final String BROADCAST_INTENT = "android.intent.action.VOICE_TESTAPP";
@@ -136,6 +139,8 @@
public static final String BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT =
"android.intent.action.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT";
+ public static final String BROADCAST_HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_RESULT_INTENT =
+ "android.intent.action.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_RESULT";
public static final String KEY_SERVICE_TYPE = "serviceType";
public static final String KEY_TEST_EVENT = "testEvent";
public static final String KEY_TEST_RESULT = "testResult";
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
index 2af7e13..5fb5e11 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
@@ -19,6 +19,7 @@
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import android.content.Intent;
+import android.media.AudioFormat;
import android.os.PersistableBundle;
import android.os.SharedMemory;
import android.service.voice.AlwaysOnHotwordDetector;
@@ -30,6 +31,7 @@
import java.nio.ByteBuffer;
import java.util.Locale;
+import java.util.Objects;
/**
* This service included a basic HotwordDetectionService for testing.
@@ -43,6 +45,7 @@
public static byte[] FAKE_BYTE_ARRAY_DATA = new byte[] {1, 2, 3};
private boolean mReady = false;
+ private AlwaysOnHotwordDetector mAlwaysOnHotwordDetector = null;
@Override
public void onReady() {
@@ -61,21 +64,32 @@
}
final int testEvent = intent.getIntExtra(Utils.KEY_TEST_EVENT, -1);
+ Log.i(TAG, "testEvent = " + testEvent);
if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST) {
runWithShellPermissionIdentity(() -> {
- callCreateAlwaysOnHotwordDetector();
+ mAlwaysOnHotwordDetector = callCreateAlwaysOnHotwordDetector();
});
} else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_WITHOUT_PERMISSION_TEST) {
callCreateAlwaysOnHotwordDetector();
+ } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST) {
+ runWithShellPermissionIdentity(() -> {
+ if (mAlwaysOnHotwordDetector != null) {
+ mAlwaysOnHotwordDetector.triggerHardwareRecognitionEventForTest(/* status */ 0,
+ /* soundModelHandle */ 100, /* captureAvailable */ true,
+ /* captureSession */ 101, /* captureDelayMs */ 1000,
+ /* capturePreambleMs */ 1001, /* triggerInData */ true,
+ createFakeAudioFormat(), new byte[1024]);
+ }
+ });
}
return START_NOT_STICKY;
}
- private void callCreateAlwaysOnHotwordDetector() {
+ private AlwaysOnHotwordDetector callCreateAlwaysOnHotwordDetector() {
Log.i(TAG, "callCreateAlwaysOnHotwordDetector()");
try {
- createAlwaysOnHotwordDetector(/* keyphrase */ "Hello Google",
+ return createAlwaysOnHotwordDetector(/* keyphrase */ "Hello Google",
Locale.forLanguageTag("en-US"),
createFakePersistableBundleData(),
createFakeSharedMemoryData(),
@@ -88,6 +102,7 @@
@Override
public void onDetected(AlwaysOnHotwordDetector.EventPayload eventPayload) {
Log.i(TAG, "onDetected");
+ broadcastOnDetectedEvent();
}
@Override
@@ -121,6 +136,7 @@
Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SECURITY_EXCEPTION);
}
+ return null;
}
private void broadcastIntentWithResult(String intentName, int result) {
@@ -150,6 +166,13 @@
return persistableBundle;
}
+ private AudioFormat createFakeAudioFormat() {
+ return new AudioFormat.Builder()
+ .setSampleRate(32000)
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+ .setChannelMask(AudioFormat.CHANNEL_IN_MONO).build();
+ }
+
private void verifyHotwordDetectionServiceInitializedStatus(int status) {
if (status == HotwordDetectionService.INITIALIZATION_STATUS_SUCCESS) {
broadcastIntentWithResult(
@@ -157,4 +180,10 @@
Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
}
}
+
+ private void broadcastOnDetectedEvent() {
+ broadcastIntentWithResult(
+ Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_RESULT_INTENT,
+ Utils.HOTWORD_DETECTION_SERVICE_ONDETECT_SUCCESS);
+ }
}
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
index e37ec08..8f2535f 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
@@ -28,6 +28,8 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.function.IntConsumer;
public class MainHotwordDetectionService extends HotwordDetectionService {
@@ -44,7 +46,39 @@
Log.w(TAG, "callback is null");
return;
}
- callback.onDetected(null);
+ if (audioStream == null) {
+ Log.w(TAG, "audioStream is null");
+ return;
+ }
+
+ long startTime = System.currentTimeMillis();
+ try (InputStream fis =
+ new ParcelFileDescriptor.AutoCloseInputStream(audioStream)) {
+
+ // We added the fake audio data and set "hotword!" string at the head. Then we simulated
+ // to verify the audio data with "hotword!" in HotwordDetectionService. If the audio
+ // data includes "hotword!", it means that the hotword is valid.
+ while (fis.available() < 8) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ // Nothing
+ }
+ if (System.currentTimeMillis() - startTime > timeoutMillis) {
+ Log.w(TAG, "Over timeout");
+ return;
+ }
+ }
+ Log.d(TAG, "fis.available() = " + fis.available());
+ byte[] buffer = new byte[8];
+ fis.read(buffer, 0, 8);
+ if(isSame(buffer, new byte[] {'h', 'o', 't', 'w', 'o', 'r', 'd', '!'}, buffer.length)) {
+ Log.d(TAG, "call callback.onDetected");
+ callback.onDetected(null);
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to read data : ", e);
+ }
}
@Override
@@ -81,4 +115,19 @@
statusCallback.accept(INITIALIZATION_STATUS_SUCCESS);
}
}
+
+ private boolean isSame(byte[] array1, byte[] array2, int length) {
+ if (length <= 0) {
+ return false;
+ }
+ if (array1 == null || array2 == null || array1.length < length || array2.length < length) {
+ return false;
+ }
+ for (int i = 0; i < length; i++) {
+ if (array1[i] != array2[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
index 6fe406e..700f891 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
@@ -80,6 +80,42 @@
receiver.unregisterQuietly();
}
+ @Test
+ public void testHotwordDetectionService_onDetectFromDsp_success()
+ throws Throwable {
+ // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
+ final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(mContext,
+ Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT);
+ receiver.register();
+
+ mActivityTestRule.getScenario().onActivity(activity -> {
+ activity.triggerHotwordDetectionServiceTest(
+ Utils.HOTWORD_DETECTION_SERVICE_BASIC,
+ Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST);
+ });
+
+ receiver.awaitForBroadcast(TIMEOUT_MS);
+ receiver.unregisterQuietly();
+
+ // Use AlwaysOnHotwordDetector to test the onDetect function of HotwordDetectionService
+ final BlockingBroadcastReceiver onDetectReceiver = new BlockingBroadcastReceiver(mContext,
+ Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_RESULT_INTENT);
+ onDetectReceiver.register();
+
+ mActivityTestRule.getScenario().onActivity(activity -> {
+ activity.triggerHotwordDetectionServiceTest(
+ Utils.HOTWORD_DETECTION_SERVICE_BASIC,
+ Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST);
+ });
+
+ final Intent intent = onDetectReceiver.awaitForBroadcast(TIMEOUT_MS);
+ assertThat(intent).isNotNull();
+ assertThat(intent.getIntExtra(Utils.KEY_TEST_RESULT, -1)).isEqualTo(
+ Utils.HOTWORD_DETECTION_SERVICE_ONDETECT_SUCCESS);
+
+ onDetectReceiver.unregisterQuietly();
+ }
+
@Override
public String getVoiceInteractionService() {
return "android.voiceinteraction.cts/"
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsFixedCollectionAdapterTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsFixedCollectionAdapterTest.java
index e700530..50bff42 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsFixedCollectionAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsFixedCollectionAdapterTest.java
@@ -30,6 +30,7 @@
import android.app.Activity;
import android.app.Instrumentation;
import android.app.PendingIntent;
+import android.appwidget.AppWidgetHostView;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -38,6 +39,7 @@
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
import android.widget.Adapter;
import android.widget.AdapterViewFlipper;
import android.widget.CompoundButton;
@@ -89,9 +91,12 @@
mActivity = mActivityRule.getActivity();
mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_adapters);
- ViewGroup parent = (ViewGroup) mActivity.findViewById(R.id.remoteView_host);
- mView = mRemoteViews.apply(mActivity, parent);
- parent.addView(mView);
+ ViewGroup parent = mActivity.findViewById(R.id.remoteView_host);
+ AppWidgetHostView hostView = new AppWidgetHostView(mActivity);
+ parent.addView(hostView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+
+ mView = mRemoteViews.apply(mActivity, hostView);
+ hostView.addView(mView);
mListView = mView.findViewById(R.id.remoteView_list);
mGridView = mView.findViewById(R.id.remoteView_grid);
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
index 61a939b..689beaf 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
@@ -1171,6 +1171,23 @@
resolveDimenOffset(6.5f, COMPLEX_UNIT_DIP, displayMetrics));
});
+ // Test that zeros resolve to 0
+ mRemoteViews.setViewLayoutMarginAttr(R.id.remoteView_text, MARGIN_LEFT, 0);
+ mRemoteViews.setViewLayoutMarginAttr(R.id.remoteView_text, MARGIN_TOP, 0);
+ mRemoteViews.setViewLayoutMarginAttr(R.id.remoteView_text, MARGIN_RIGHT, 0);
+ applyNightModeThenApplyAndTest(false, () -> {
+ View textView = mResult.findViewById(R.id.remoteView_text);
+ DisplayMetrics displayMetrics = textView.getResources().getDisplayMetrics();
+ assertMargins(textView, 0, 0, 0,
+ resolveDimenOffset(4.5f, COMPLEX_UNIT_DIP, displayMetrics));
+ });
+ applyNightModeThenApplyAndTest(true, () -> {
+ View textView = mResult.findViewById(R.id.remoteView_text);
+ DisplayMetrics displayMetrics = textView.getResources().getDisplayMetrics();
+ assertMargins(textView, 0, 0, 0,
+ resolveDimenOffset(6.5f, COMPLEX_UNIT_DIP, displayMetrics));
+ });
+
mRemoteViews.setViewLayoutMarginAttr(
R.id.remoteView_text, MARGIN_LEFT, R.attr.themeColor);
assertThrowsOnReapply(ActionException.class);
@@ -1244,6 +1261,10 @@
assertEquals(
textView.getResources().getDimensionPixelSize(R.dimen.textview_fixed_width),
textView.getLayoutParams().width);
+
+ mRemoteViews.setViewLayoutWidthDimen(R.id.remoteView_text, 0);
+ mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
+ assertEquals(0, textView.getLayoutParams().width);
}
@Test
@@ -1256,6 +1277,10 @@
textView.getResources().getDisplayMetrics()),
textView.getLayoutParams().width);
+ mRemoteViews.setViewLayoutWidthAttr(R.id.remoteView_text, 0);
+ mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
+ assertEquals(0, textView.getLayoutParams().width);
+
mRemoteViews.setViewLayoutWidthAttr(R.id.remoteView_text, R.attr.themeColor);
assertThrowsOnReapply(ActionException.class);
}
@@ -1289,6 +1314,10 @@
assertEquals(
textView.getResources().getDimensionPixelSize(R.dimen.textview_fixed_height),
textView.getLayoutParams().height);
+
+ mRemoteViews.setViewLayoutHeightDimen(R.id.remoteView_text, 0);
+ mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
+ assertEquals(0, textView.getLayoutParams().height);
}
@Test
@@ -1301,6 +1330,10 @@
textView.getResources().getDisplayMetrics()),
textView.getLayoutParams().height);
+ mRemoteViews.setViewLayoutHeightAttr(R.id.remoteView_text, 0);
+ mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
+ assertEquals(0, textView.getLayoutParams().height);
+
mRemoteViews.setViewLayoutHeightAttr(
R.id.remoteView_text, R.attr.themeColor);
assertThrowsOnReapply(ActionException.class);
@@ -1316,6 +1349,11 @@
mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
assertEquals(expectedValue, textView.getCompoundDrawablePadding());
+ // test that passing 0 for the dimen sets 0 on the method.
+ mRemoteViews.setIntDimen(R.id.remoteView_text, "setCompoundDrawablePadding", 0);
+ mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
+ assertEquals(0, textView.getCompoundDrawablePadding());
+
mRemoteViews.setIntDimen(R.id.remoteView_text, "setCompoundDrawablePadding",
R.color.testcolor1);
assertThrowsOnReapply(ActionException.class);
@@ -1367,6 +1405,18 @@
textView.getCompoundDrawablePadding());
});
+ // test that 0 resolves to 0
+ mRemoteViews.setIntDimenAttr(R.id.remoteView_text, "setCompoundDrawablePadding", 0);
+ applyNightModeThenApplyAndTest(false, () -> {
+ TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text);
+ assertEquals(0, textView.getCompoundDrawablePadding());
+ });
+
+ applyNightModeThenApplyAndTest(true, () -> {
+ TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text);
+ assertEquals(0, textView.getCompoundDrawablePadding());
+ });
+
mRemoteViews.setIntDimenAttr(R.id.remoteView_text, "setCompoundDrawablePadding",
R.attr.themeColor);
assertThrowsOnReapply(ActionException.class);
@@ -1383,6 +1433,11 @@
assertEquals(textView.getResources().getDimension(R.dimen.remoteviews_float_dimen),
textView.getTextScaleX(), 1e-4f);
+ // test that passing 0 for the dimen sets 0f on the method.
+ mRemoteViews.setFloatDimen(R.id.remoteView_text, "setTextScaleX", 0);
+ mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
+ assertEquals(0f, textView.getTextScaleX(), 1e-4f);
+
mRemoteViews.setFloatDimen(R.id.remoteView_text, "setTextScaleX", R.color.testcolor1);
assertThrowsOnReapply(ActionException.class);
}
@@ -1431,6 +1486,18 @@
textView.getResources().getDisplayMetrics()), textView.getTextScaleX(), 1e-4f);
});
+ // test that 0 resolves to 0
+ mRemoteViews.setFloatDimenAttr(R.id.remoteView_text, "setTextScaleX", 0);
+ applyNightModeThenApplyAndTest(false, () -> {
+ TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text);
+ assertEquals(0f, textView.getTextScaleX(), 1e-4f);
+ });
+
+ applyNightModeThenApplyAndTest(true, () -> {
+ TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text);
+ assertEquals(0f, textView.getTextScaleX(), 1e-4f);
+ });
+
mRemoteViews.setFloatDimenAttr(R.id.remoteView_text, "setTextScaleX",
R.attr.themeColor);
assertThrowsOnReapply(ActionException.class);
@@ -1445,6 +1512,10 @@
mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
assertSameColorStateList(ColorStateList.valueOf(expectedValue), textView.getTextColors());
+ mRemoteViews.setColor(R.id.remoteView_text, "setTextColor", 0);
+ mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
+ assertSameColorStateList(ColorStateList.valueOf(0), textView.getTextColors());
+
mRemoteViews.setColor(R.id.remoteView_text, "setTextColor", R.dimen.popup_row_height);
assertThrowsOnReapply(ActionException.class);
}
@@ -1465,6 +1536,20 @@
assertSameColorStateList(ColorStateList.valueOf(0x0f00ffff), textView.getTextColors());
});
+ // Set to 0 and test that the colors are set to 0
+ mRemoteViews.setColorAttr(R.id.remoteView_text, "setTextColor", 0);
+
+ applyNightModeThenApplyAndTest(false, () -> {
+ TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text);
+ assertSameColorStateList(ColorStateList.valueOf(0), textView.getTextColors());
+ });
+
+ // Switch to night mode
+ applyNightModeThenApplyAndTest(true, () -> {
+ TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text);
+ assertSameColorStateList(ColorStateList.valueOf(0), textView.getTextColors());
+ });
+
mRemoteViews.setColorAttr(R.id.remoteView_text, "setTextColor", R.attr.themeDimension);
assertThrowsOnReapply(ActionException.class);
}
@@ -1511,7 +1596,19 @@
progressBar.getProgressTintList());
});
- mRemoteViews.setColorAttr(R.id.remoteView_text, "setTextColor", R.attr.themeDimension);
+ mRemoteViews.setColorStateListAttr(R.id.remoteView_progress, "setProgressTintList", 0);
+ applyNightModeThenApplyAndTest(false, () -> {
+ ProgressBar progressBar = mResult.findViewById(R.id.remoteView_progress);
+ assertSameColorStateList(null, progressBar.getProgressTintList());
+ });
+
+ applyNightModeThenApplyAndTest(true, () -> {
+ ProgressBar progressBar = mResult.findViewById(R.id.remoteView_progress);
+ assertSameColorStateList(null, progressBar.getProgressTintList());
+ });
+
+ mRemoteViews.setColorAttr(R.id.remoteView_progress,
+ "setProgressTintList", R.attr.themeDimension);
assertThrowsOnReapply(ActionException.class);
}
@@ -1534,22 +1631,27 @@
@Test
public void testSetColorStateList_fromResources() throws Throwable {
- TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text);
+ ProgressBar progressBar = (ProgressBar) mResult.findViewById(R.id.remoteView_progress);
ColorStateList expectedValue = mContext.getColorStateList(R.color.testcolorstatelist1);
- mRemoteViews.setColorStateList(R.id.remoteView_text, "setTextColor",
+ mRemoteViews.setColorStateList(R.id.remoteView_progress, "setProgressTintList",
R.color.testcolorstatelist1);
mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
- assertSameColorStateList(expectedValue, textView.getTextColors());
+ assertSameColorStateList(expectedValue, progressBar.getProgressTintList());
- mRemoteViews.setColorStateList(R.id.remoteView_text, "setTextColor",
+ mRemoteViews.setColorStateList(R.id.remoteView_progress, "setProgressTintList",
R.color.testcolor1);
mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
expectedValue = mContext.getResources().getColorStateList(R.color.testcolor1,
mContext.getTheme());
- assertSameColorStateList(expectedValue, textView.getTextColors());
+ assertSameColorStateList(expectedValue, progressBar.getProgressTintList());
- mRemoteViews.setColorStateList(R.id.remoteView_text, "setTextColor",
+ // 0 should resolve to null
+ mRemoteViews.setColorStateList(R.id.remoteView_progress, "setProgressTintList", 0);
+ mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult));
+ assertSameColorStateList(null, progressBar.getProgressTintList());
+
+ mRemoteViews.setColorStateList(R.id.remoteView_progress, "setProgressTintList",
R.dimen.popup_row_height);
assertThrowsOnReapply(ActionException.class);
}
@@ -1812,7 +1914,8 @@
}
private void assertSameColorStateList(ColorStateList expected, ColorStateList actual) {
- assertEquals(expected.toString(), actual.toString());
+ assertEquals(expected == null ? null : expected.toString(),
+ actual == null ? null : actual.toString());
}
private <T extends Throwable> void assertThrowsOnReapply(Class<T> klass) throws Throwable {
diff --git a/tests/translation/src/android/translation/cts/CtsTranslationService.java b/tests/translation/src/android/translation/cts/CtsTranslationService.java
index 33540b6..b60dce6 100644
--- a/tests/translation/src/android/translation/cts/CtsTranslationService.java
+++ b/tests/translation/src/android/translation/cts/CtsTranslationService.java
@@ -104,8 +104,15 @@
@Override
public void onCreateTranslationSession(@NonNull TranslationContext translationContext,
- int sessionId) {
+ int sessionId, @NonNull Consumer<Boolean> callback) {
Log.v(TAG, "onCreateTranslationSession");
+ callback.accept(true);
+ }
+
+ @Override
+ public void onCreateTranslationSession(@NonNull TranslationContext translationContext,
+ int sessionId) {
+ Log.v(TAG, "deprecated");
}
@Override