Merge "cts: make the softap info check is optional" into rvc-dev
diff --git a/apps/CameraITS/build/scripts/gpylint_rcfile b/apps/CameraITS/build/scripts/gpylint_rcfile
index f92c613..b9c16f4 100644
--- a/apps/CameraITS/build/scripts/gpylint_rcfile
+++ b/apps/CameraITS/build/scripts/gpylint_rcfile
@@ -318,7 +318,7 @@
[MASTER]
-# Add files or directories to the blacklist. They should be base names, not
+# Add files or directories to the ignorelist. They should be base names, not
# paths.
ignore=CVS
diff --git a/apps/CameraITS/tests/scene3/test_flip_mirror.py b/apps/CameraITS/tests/scene3/test_flip_mirror.py
index b4677c7..0a90712 100644
--- a/apps/CameraITS/tests/scene3/test_flip_mirror.py
+++ b/apps/CameraITS/tests/scene3/test_flip_mirror.py
@@ -64,7 +64,7 @@
patch = 255 * its.cv2image.gray_scale_img(patch)
patch = its.cv2image.scale_img(patch.astype(np.uint8), chart.scale)
- # sanity check on image
+ # validity check on image
assert np.max(patch)-np.min(patch) > 255/8
# save full images if in debug
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index e54fdb5..14e381c 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -319,7 +319,7 @@
# 3. Child"s width > 0.1*Image width
# 4. Child"s height > 0.1*Image height
# 5. 0.25*Parent"s area < Child"s area < 0.45*Parent"s area
- # 6. Child is a black, and Parent is white
+ # 6. Child == 0, and Parent == 255
# 7. Center of Child and center of parent should overlap
if (prt_shape["width"] * 0.56 < child_shape["width"]
< prt_shape["width"] * 0.76
diff --git a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
index 649fc2a..2d08267 100644
--- a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
+++ b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
@@ -282,7 +282,7 @@
# 3. Child's width > 0.1*Image width
# 4. Child's height > 0.1*Image height
# 5. 0.25*Parent's area < Child's area < 0.45*Parent's area
- # 6. Child is a black, and Parent is white
+ # 6. Child == 0, and Parent == 255
# 7. Center of Child and center of parent should overlap
if (prt_shape['width'] * 0.56 < child_shape['width']
< prt_shape['width'] * 0.76
@@ -360,7 +360,7 @@
world coordinates.
Reproject the world coordinates back to pixel coordinates and compare
- against originals as a sanity check.
+ against originals as a validity check.
Compare the circle sizes if the focal lengths of the cameras are
different using
@@ -583,7 +583,7 @@
circle[i]['x'], circle[i]['y'], r[i], t[i], k[i],
chart_distance)
- # Back convert to image coordinates for sanity check
+ # Back convert to image coordinates for round-trip check
x_p = {}
y_p = {}
x_p[i_2nd], y_p[i_2nd] = convert_to_image_coordinates(
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index 9292f6a3..f1b1d36 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -128,7 +128,7 @@
else:
events, frames, _, h = load_data()
- # Sanity check camera timestamps are enclosed by sensor timestamps
+ # Check that camera timestamps are enclosed by sensor timestamps
# This will catch bugs where camera and gyro timestamps go completely out
# of sync
cam_times = get_cam_times(events["cam"])
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index b6579a8..36e6b71 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -30,7 +30,7 @@
import its.image
import rotation_rig as rot
-# For sanity checking the installed APK's target SDK version
+# For checking the installed APK's target SDK version
MIN_SUPPORTED_SDK_VERSION = 28 # P
CHART_DELAY = 1 # seconds
@@ -429,7 +429,7 @@
device_id_arg = "device=" + device_id
print "Testing device " + device_id
- # Sanity check CtsVerifier SDK level
+ # Check CtsVerifier SDK level
# Here we only do warning as there is no guarantee on pm dump output formt not changed
# Also sometimes it's intentional to run mismatched versions
cmd = "adb -s %s shell pm dump com.android.cts.verifier" % (device_id)
@@ -473,7 +473,7 @@
with ItsSession() as cam:
cam.check_its_version_compatible()
- # Sanity Check for devices
+ # Correctness check for devices
device_bfp = its.device.get_device_fingerprint(device_id)
assert device_bfp is not None
diff --git a/hostsidetests/angle/Android.bp b/hostsidetests/angle/Android.bp
index 3125610..dac193f 100644
--- a/hostsidetests/angle/Android.bp
+++ b/hostsidetests/angle/Android.bp
@@ -22,7 +22,6 @@
"cts",
"vts10",
"general-tests",
- "mts"
],
libs: [
"cts-tradefed",
diff --git a/hostsidetests/angle/app/common/Android.bp b/hostsidetests/angle/app/common/Android.bp
index 508ce2d..fe33a37 100644
--- a/hostsidetests/angle/app/common/Android.bp
+++ b/hostsidetests/angle/app/common/Android.bp
@@ -20,6 +20,5 @@
test_suites: [
"gts",
"ats",
- "mts"
],
}
diff --git a/hostsidetests/angle/app/driverTest/Android.bp b/hostsidetests/angle/app/driverTest/Android.bp
index 1bfc779..9b2adb2 100644
--- a/hostsidetests/angle/app/driverTest/Android.bp
+++ b/hostsidetests/angle/app/driverTest/Android.bp
@@ -22,7 +22,6 @@
test_suites: [
"cts",
"vts10",
- "mts"
],
compile_multilib: "both",
static_libs: [
diff --git a/hostsidetests/angle/app/driverTestSecondary/Android.bp b/hostsidetests/angle/app/driverTestSecondary/Android.bp
index 22f3c2f..fad514e 100644
--- a/hostsidetests/angle/app/driverTestSecondary/Android.bp
+++ b/hostsidetests/angle/app/driverTestSecondary/Android.bp
@@ -24,7 +24,6 @@
test_suites: [
"cts",
"vts10",
- "mts"
],
compile_multilib: "both",
static_libs: [
diff --git a/hostsidetests/apex/src/android/apex/cts/ApexTest.java b/hostsidetests/apex/src/android/apex/cts/ApexTest.java
index 081da9b..c2ca8bc 100644
--- a/hostsidetests/apex/src/android/apex/cts/ApexTest.java
+++ b/hostsidetests/apex/src/android/apex/cts/ApexTest.java
@@ -41,7 +41,9 @@
|| systemProduct.equals("aosp_arm_ab") // _ab for Legacy GSI
|| systemProduct.equals("aosp_arm64_ab")
|| systemProduct.equals("aosp_x86_ab")
- || systemProduct.equals("aosp_x86_64_ab");
+ || systemProduct.equals("aosp_x86_64_ab")
+ || systemProduct.equals("aosp_tv_arm")
+ || systemProduct.equals("aosp_tv_arm64");
}
/**
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
index 1c83284..fc63925 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
@@ -18,6 +18,8 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.device.DeviceNotAvailableException;
+
import com.google.common.collect.ImmutableSet;
/**
@@ -124,7 +126,7 @@
}
public void testRestrictStorageAccessFrameworkEnabled_blockFromTree() throws Exception {
- if (isAtLeastR()) {
+ if (isAtLeastR() && isSupportedHardware()) {
runDeviceCompatTest(CLIENT_PKG, ".DocumentsClientTest",
"testRestrictStorageAccessFrameworkEnabled_blockFromTree",
/* enabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
@@ -133,7 +135,7 @@
}
public void testRestrictStorageAccessFrameworkDisabled_notBlockFromTree() throws Exception {
- if (isAtLeastR()) {
+ if (isAtLeastR() && isSupportedHardware()) {
runDeviceCompatTest(CLIENT_PKG, ".DocumentsClientTest",
"testRestrictStorageAccessFrameworkDisabled_notBlockFromTree",
/* enabledChanges */ ImmutableSet.of(),
@@ -153,4 +155,17 @@
return false;
}
}
+
+ private boolean isSupportedHardware() {
+ try {
+ if (getDevice().hasFeature("feature:android.hardware.type.television")
+ || getDevice().hasFeature("feature:android.hardware.type.watch")
+ || getDevice().hasFeature("feature:android.hardware.type.automotive")) {
+ return false;
+ }
+ } catch (DeviceNotAvailableException e) {
+ return true;
+ }
+ return true;
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
index e44d70d..f507d40 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
@@ -45,6 +45,7 @@
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import android.test.InstrumentationTestCase;
@@ -102,7 +103,11 @@
if (!isTV(getContext())) {
UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
- uiScrollable.scrollTextIntoView("internal storage");
+ try {
+ uiScrollable.scrollTextIntoView("internal storage");
+ } catch (UiObjectNotFoundException e) {
+ // Scrolling can fail if the UI is not scrollable
+ }
device.findObject(new UiSelector().textContains("internal storage")).click();
device.waitForIdle();
}
diff --git a/hostsidetests/backup/src/android/cts/backup/MultiUserBackupStateTest.java b/hostsidetests/backup/src/android/cts/backup/MultiUserBackupStateTest.java
index 3e7c1da..2f4164f 100644
--- a/hostsidetests/backup/src/android/cts/backup/MultiUserBackupStateTest.java
+++ b/hostsidetests/backup/src/android/cts/backup/MultiUserBackupStateTest.java
@@ -23,6 +23,8 @@
import com.android.compatibility.common.util.CommonTestUtils;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.log.LogUtil.CLog;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -40,6 +42,12 @@
private Optional<Integer> mProfileUserId = Optional.empty();
+ /**
+ * User ID for the system user.
+ * The value is from the UserHandle class.
+ */
+ protected static final int USER_SYSTEM = 0;
+
/** Create the profile and start it. */
@Before
@Override
@@ -79,11 +87,21 @@
assertTrue(mBackupUtils.isBackupActivatedForUser(profileUserId));
- assertTrue(getDevice().removeUser(profileUserId));
+ removeUser(profileUserId);
mProfileUserId = Optional.empty();
CommonTestUtils.waitUntil("wait for backup to be deactivated for removed user",
BACKUP_DEACTIVATION_TIMEOUT_SECONDS,
() -> !mBackupUtils.isBackupActivatedForUser(profileUserId));
}
+
+ private void removeUser(int userId) throws Exception {
+ if (getDevice().listUsers().contains(userId) && userId != USER_SYSTEM) {
+ // Don't log output, as tests sometimes set no debug user restriction, which
+ // causes this to fail, we should still continue and remove the user.
+ CLog.d("Stopping and removing user " + userId);
+ getDevice().stopUser(userId, true, true);
+ assertTrue("Couldn't remove user", getDevice().removeUser(userId));
+ }
+ }
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
index f59803b..ed420f1 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
@@ -16,7 +16,6 @@
package com.android.cts.deviceandprofileowner;
import android.app.admin.DevicePolicyManager;
-import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.util.Log;
/**
@@ -34,35 +33,32 @@
super.setUp();
}
- public void testSetScreenCaptureDisabled_false() throws Exception {
+ public void testSetScreenCaptureDisabled_false() {
mDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, false);
assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
}
- public void testSetScreenCaptureDisabled_true() throws Exception {
+ public void testSetScreenCaptureDisabled_true() {
mDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, true);
assertTrue(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
assertTrue(mDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
}
- public void testSetScreenCaptureDisabledOnParent() throws Exception {
+ public void testSetScreenCaptureDisabledOnParent_false() {
DevicePolicyManager parentDevicePolicyManager =
mDevicePolicyManager.getParentProfileInstance(ADMIN_RECEIVER_COMPONENT);
- boolean initial = parentDevicePolicyManager.getScreenCaptureDisabled(
- ADMIN_RECEIVER_COMPONENT);
-
- parentDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, true);
- assertTrue(parentDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
- assertTrue(parentDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
- testScreenCaptureImpossible();
-
parentDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, false);
assertFalse(parentDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
assertFalse(parentDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
- testScreenCapturePossible();
+ }
- parentDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, initial);
+ public void testSetScreenCaptureDisabledOnParent_true() {
+ DevicePolicyManager parentDevicePolicyManager =
+ mDevicePolicyManager.getParentProfileInstance(ADMIN_RECEIVER_COMPONENT);
+ parentDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, true);
+ assertTrue(parentDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
+ assertTrue(parentDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
}
public void testScreenCaptureImpossible() throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 1301d2a..048468c 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -2225,13 +2225,9 @@
? "testScreenCaptureImpossible"
: "testScreenCapturePossible";
- if (userId == mPrimaryUserId) {
- // If testing for user-0, also make sure the existing screen can't be captured.
- executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
- }
-
startSimpleActivityAsUser(userId);
executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
+ forceStopPackageForUser(TEST_APP_PKG, userId);
}
protected void setScreenCaptureDisabled_assist(int userId, boolean disabled) throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileContactsTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileContactsTest.java
index 2ed1e30..5492cf2 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileContactsTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileContactsTest.java
@@ -150,6 +150,9 @@
"settings put --user " + mProfileUserId
+ " secure managed_profile_contact_remote_search 1");
+ // Wait for updating cache
+ waitForBroadcastIdle();
+
// Add test account
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testAddTestAccount", mParentUserId);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
index f575fc7..875803c 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
@@ -49,6 +49,8 @@
private static final String ACTION_WIPE_DATA =
"com.android.cts.deviceandprofileowner.WIPE_DATA";
+ private static final String TEST_APP_APK = "CtsSimpleApp.apk";
+ private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
private static final String DUMMY_IME_APK = "DummyIme.apk";
private static final String DUMMY_IME_PKG = "com.android.cts.dummyime";
private static final String DUMMY_IME_COMPONENT = DUMMY_IME_PKG + "/.DummyIme";
@@ -554,8 +556,41 @@
if (!mHasFeature) {
return;
}
+ installAppAsUser(DEVICE_ADMIN_APK, mPrimaryUserId);
+ setPoAsUser(mPrimaryUserId);
+
+ try {
+ setScreenCaptureDisabled(true);
+ } finally {
+ setScreenCaptureDisabled(false);
+ }
+ }
+
+ private void takeScreenCaptureAsUser(int userId, String testMethodName) throws Exception {
+ installAppAsUser(TEST_APP_APK, /* grantPermissions */ true, /* dontKillApp */ true, userId);
+ startActivityAsUser(userId, TEST_APP_PKG, TEST_APP_PKG + ".SimpleActivity");
runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".ScreenCaptureDisabledTest",
- "testSetScreenCaptureDisabledOnParent", mUserId);
+ testMethodName, userId);
+ forceStopPackageForUser(TEST_APP_PKG, userId);
+ }
+
+ private void setScreenCaptureDisabled(boolean disabled) throws Exception {
+ String testMethodName = disabled
+ ? "testSetScreenCaptureDisabledOnParent_true"
+ : "testSetScreenCaptureDisabledOnParent_false";
+ runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".ScreenCaptureDisabledTest",
+ testMethodName, mUserId);
+
+ testMethodName = disabled
+ ? "testScreenCaptureImpossible"
+ : "testScreenCapturePossible";
+
+ // Test personal profile
+ takeScreenCaptureAsUser(mPrimaryUserId, testMethodName);
+
+ // Test managed profile. This should not be disabled when screen capture is disabled on
+ // the parent by the profile owner of an organization-owned device.
+ takeScreenCaptureAsUser(mUserId, "testScreenCapturePossible");
}
private void assertHasNoUser(int userId) throws DeviceNotAvailableException {
diff --git a/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java b/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java
index 460181d..f7dcec1 100644
--- a/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java
@@ -72,8 +72,6 @@
AlarmManagerIncidentTest.verifyAlarmManagerServiceDumpProto(dump.getAlarm(), filterLevel);
- MemInfoIncidentTest.verifyMemInfoDumpProto(dump.getMeminfo(), filterLevel);
-
// GraphicsStats is expected to be all AUTOMATIC.
WindowManagerIncidentTest.verifyWindowManagerServiceDumpProto(dump.getWindow(), filterLevel);
diff --git a/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java
deleted file mode 100644
index 2747972..0000000
--- a/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2016 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.server.cts;
-
-import com.android.server.am.MemInfoDumpProto;
-import com.android.server.am.MemInfoDumpProto.AppData;
-import com.android.server.am.MemInfoDumpProto.MemItem;
-import com.android.server.am.MemInfoDumpProto.ProcessMemory;
-
-/** Test to check that ActivityManager properly outputs meminfo data. */
-public class MemInfoIncidentTest extends ProtoDumpTestCase {
-
- public void testMemInfoDump() throws Exception {
- final MemInfoDumpProto dump =
- getDump(MemInfoDumpProto.parser(), "dumpsys -t 30000 meminfo -a --proto");
-
- verifyMemInfoDumpProto(dump, PRIVACY_NONE);
- }
-
- static void verifyMemInfoDumpProto(MemInfoDumpProto dump, final int filterLevel) throws Exception {
- assertTrue(dump.getUptimeDurationMs() >= 0);
- assertTrue(dump.getElapsedRealtimeMs() >= 0);
-
- for (ProcessMemory pm : dump.getNativeProcessesList()) {
- testProcessMemory(pm);
- }
-
- for (AppData ad : dump.getAppProcessesList()) {
- testAppData(ad);
- }
-
- for (MemItem mi : dump.getTotalPssByProcessList()) {
- testMemItem(mi);
- }
- for (MemItem mi : dump.getTotalPssByOomAdjustmentList()) {
- testMemItem(mi);
- }
- for (MemItem mi : dump.getTotalPssByCategoryList()) {
- testMemItem(mi);
- }
-
- assertTrue(0 <= dump.getTotalRamKb());
- assertTrue(0 <= dump.getCachedPssKb());
- assertTrue(0 <= dump.getCachedKernelKb());
- assertTrue(0 <= dump.getFreeKb());
- assertTrue(0 <= dump.getUsedPssKb());
- assertTrue(0 <= dump.getUsedKernelKb());
-
- // Ideally lost RAM would not be negative, but there's an issue where it's sometimes
- // calculated to be negative.
- // TODO: re-enable check once the underlying bug has been fixed.
- // assertTrue(0 <= dump.getLostRamKb());
-
- assertTrue(0 <= dump.getTotalZramKb());
- assertTrue(0 <= dump.getZramPhysicalUsedInSwapKb());
- assertTrue(0 <= dump.getTotalZramSwapKb());
-
- assertTrue(0 <= dump.getKsmSharingKb());
- assertTrue(0 <= dump.getKsmSharedKb());
- assertTrue(0 <= dump.getKsmUnsharedKb());
- assertTrue(0 <= dump.getKsmVolatileKb());
-
- assertTrue("Tuning_mb (" + dump.getTuningMb() + ") is not positive", 0 < dump.getTuningMb());
- assertTrue(0 < dump.getTuningLargeMb());
-
- assertTrue(0 <= dump.getOomKb());
-
- assertTrue(0 < dump.getRestoreLimitKb());
- }
-
- private static void testProcessMemory(ProcessMemory pm) throws Exception {
- assertNotNull(pm);
-
- assertTrue(0 < pm.getPid());
- // On most Linux machines, the max pid value is 32768 (=2^15), but, it can be set to any
- // value up to 4194304 (=2^22) if necessary.
- assertTrue(4194304 >= pm.getPid());
-
- testHeapInfo(pm.getNativeHeap());
- testHeapInfo(pm.getDalvikHeap());
-
- for (ProcessMemory.MemoryInfo mi : pm.getOtherHeapsList()) {
- testMemoryInfo(mi);
- }
- testMemoryInfo(pm.getUnknownHeap());
- testHeapInfo(pm.getTotalHeap());
-
- for (ProcessMemory.MemoryInfo mi : pm.getDalvikDetailsList()) {
- testMemoryInfo(mi);
- }
-
- ProcessMemory.AppSummary as = pm.getAppSummary();
- assertTrue(0 <= as.getJavaHeapPssKb());
- assertTrue(0 <= as.getNativeHeapPssKb());
- assertTrue(0 <= as.getCodePssKb());
- assertTrue(0 <= as.getStackPssKb());
- assertTrue(0 <= as.getGraphicsPssKb());
- assertTrue(0 <= as.getPrivateOtherPssKb());
- assertTrue(0 <= as.getSystemPssKb());
- assertTrue(0 <= as.getTotalSwapPss());
- assertTrue(0 <= as.getTotalSwapKb());
- }
-
- private static void testMemoryInfo(ProcessMemory.MemoryInfo mi) throws Exception {
- assertNotNull(mi);
-
- assertTrue(0 <= mi.getTotalPssKb());
- assertTrue(0 <= mi.getCleanPssKb());
- assertTrue(0 <= mi.getSharedDirtyKb());
- assertTrue(0 <= mi.getPrivateDirtyKb());
- assertTrue(0 <= mi.getSharedCleanKb());
- assertTrue(0 <= mi.getPrivateCleanKb());
- assertTrue(0 <= mi.getDirtySwapKb());
- assertTrue(0 <= mi.getDirtySwapPssKb());
- }
-
- private static void testHeapInfo(ProcessMemory.HeapInfo hi) throws Exception {
- assertNotNull(hi);
-
- testMemoryInfo(hi.getMemInfo());
- assertTrue(0 <= hi.getHeapSizeKb());
- assertTrue(0 <= hi.getHeapAllocKb());
- assertTrue(0 <= hi.getHeapFreeKb());
- }
-
- private static void testAppData(AppData ad) throws Exception {
- assertNotNull(ad);
-
- testProcessMemory(ad.getProcessMemory());
-
- AppData.ObjectStats os = ad.getObjects();
- assertTrue(0 <= os.getViewInstanceCount());
- assertTrue(0 <= os.getViewRootInstanceCount());
- assertTrue(0 <= os.getAppContextInstanceCount());
- assertTrue(0 <= os.getActivityInstanceCount());
- assertTrue(0 <= os.getGlobalAssetCount());
- assertTrue(0 <= os.getGlobalAssetManagerCount());
- assertTrue(0 <= os.getLocalBinderObjectCount());
- assertTrue(0 <= os.getProxyBinderObjectCount());
- assertTrue(0 <= os.getParcelMemoryKb());
- assertTrue(0 <= os.getParcelCount());
- assertTrue(0 <= os.getBinderObjectDeathCount());
- assertTrue(0 <= os.getOpenSslSocketCount());
- assertTrue(0 <= os.getWebviewInstanceCount());
-
- AppData.SqlStats ss = ad.getSql();
- assertTrue(0 <= ss.getMemoryUsedKb());
- assertTrue(0 <= ss.getPagecacheOverflowKb());
- assertTrue(0 <= ss.getMallocSizeKb());
- for (AppData.SqlStats.Database d : ss.getDatabasesList()) {
- assertTrue(0 <= d.getPageSize());
- assertTrue(0 <= d.getDbSize());
- assertTrue(0 <= d.getLookasideB());
- }
- }
-
- private static void testMemItem(MemItem mi) throws Exception {
- assertNotNull(mi);
-
- assertTrue(0 <= mi.getPssKb());
- assertTrue(0 <= mi.getSwapPssKb());
-
- for (MemItem smi : mi.getSubItemsList()) {
- testMemItem(smi);
- }
- }
-}
diff --git a/hostsidetests/scopedstorage/Android.bp b/hostsidetests/scopedstorage/Android.bp
index 3e5096b..1a1a7f9 100644
--- a/hostsidetests/scopedstorage/Android.bp
+++ b/hostsidetests/scopedstorage/Android.bp
@@ -15,28 +15,28 @@
android_test_helper_app {
name: "CtsScopedStorageTestAppA",
manifest: "ScopedStorageTestHelper/TestAppA.xml",
- static_libs: ["androidx.test.rules", "cts-scopedstorage-lib"],
+ static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppB",
manifest: "ScopedStorageTestHelper/TestAppB.xml",
- static_libs: ["androidx.test.rules", "cts-scopedstorage-lib"],
+ static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppC",
manifest: "ScopedStorageTestHelper/TestAppC.xml",
- static_libs: ["androidx.test.rules", "cts-scopedstorage-lib"],
+ static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppCLegacy",
manifest: "ScopedStorageTestHelper/TestAppCLegacy.xml",
- static_libs: ["androidx.test.rules", "cts-scopedstorage-lib"],
+ static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
target_sdk_version: "28",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
@@ -46,9 +46,9 @@
name: "ScopedStorageTest",
manifest: "AndroidManifest.xml",
srcs: ["src/**/*.java"],
- static_libs: ["androidx.test.rules", "truth-prebuilt", "cts-scopedstorage-lib"],
+ static_libs: ["truth-prebuilt", "cts-scopedstorage-lib"],
compile_multilib: "both",
- test_suites: ["general-tests", "mts"],
+ test_suites: ["general-tests", "mts", "cts"],
sdk_version: "test_current",
java_resources: [
":CtsScopedStorageTestAppA",
@@ -61,9 +61,9 @@
name: "LegacyStorageTest",
manifest: "legacy/AndroidManifest.xml",
srcs: ["legacy/src/**/*.java"],
- static_libs: ["androidx.test.rules", "truth-prebuilt", "cts-scopedstorage-lib"],
+ static_libs: ["truth-prebuilt", "cts-scopedstorage-lib"],
compile_multilib: "both",
- test_suites: ["general-tests", "mts"],
+ test_suites: ["general-tests", "mts", "cts"],
sdk_version: "test_current",
target_sdk_version: "29",
java_resources: [
@@ -74,17 +74,15 @@
java_test_host {
name: "CtsScopedStorageHostTest",
srcs: ["host/src/**/*.java"],
- libs: ["tradefed"],
- static_libs: ["testng"],
- test_suites: ["general-tests", "mts"],
+ libs: ["tradefed", "testng"],
+ test_suites: ["general-tests", "mts", "cts"],
test_config: "AndroidTest.xml",
}
java_test_host {
name: "CtsScopedStoragePublicVolumeHostTest",
srcs: ["host/src/**/*.java"],
- libs: ["tradefed"],
- static_libs: ["testng"],
+ libs: ["tradefed", "testng"],
test_suites: ["general-tests", "mts"],
test_config: "PublicVolumeTest.xml",
}
diff --git a/hostsidetests/scopedstorage/AndroidTest.xml b/hostsidetests/scopedstorage/AndroidTest.xml
index 64599d8..43208ac 100644
--- a/hostsidetests/scopedstorage/AndroidTest.xml
+++ b/hostsidetests/scopedstorage/AndroidTest.xml
@@ -15,6 +15,10 @@
-->
<configuration description="External storage host test for legacy and scoped storage">
<option name="test-suite-tag" value="cts" />
+ <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="not_secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="ScopedStorageTest.apk" />
@@ -23,6 +27,7 @@
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="android.scopedstorage.cts.host.LegacyStorageHostTest" />
<option name="class" value="android.scopedstorage.cts.host.ScopedStorageHostTest" />
+ <option name="class" value="android.scopedstorage.cts.host.ScopedStorageInstantAppHostTest" />
</test>
<object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
index 2144def..8dfe7b7 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
@@ -29,11 +29,10 @@
import static android.scopedstorage.cts.lib.TestUtils.READDIR_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.SETATTR_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.canOpen;
-import static android.scopedstorage.cts.lib.TestUtils.getMediaContentUri;
+import static android.scopedstorage.cts.lib.TestUtils.getImageContentUri;
import android.app.Activity;
import android.content.Intent;
-import android.content.ContentResolver;
import android.content.ContentValues;
import android.os.Bundle;
import android.provider.MediaStore;
@@ -146,7 +145,7 @@
values.put(MediaStore.Images.Media.RELATIVE_PATH, relativePath);
values.put(MediaStore.Images.Media.DISPLAY_NAME, name);
- getContentResolver().insert(getMediaContentUri(), values);
+ getContentResolver().insert(getImageContentUri(), values);
final Intent intent = new Intent(queryType);
intent.putExtra(queryType, true);
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
index 330b215..8729f9b 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
@@ -20,6 +20,8 @@
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.AppModeFull;
+
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -32,6 +34,7 @@
* Runs the legacy file path access tests.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
+@AppModeFull
public class LegacyStorageHostTest extends BaseHostJUnit4Test {
private boolean isExternalStorageSetup = false;
@@ -191,4 +194,9 @@
public void testLegacyAppUpdatingOwnershipOfExistingEntry() throws Exception {
runDeviceTest("testLegacyAppUpdatingOwnershipOfExistingEntry");
}
+
+ @Test
+ public void testInsertWithUnsupportedMimeType() throws Exception {
+ runDeviceTest("testInsertWithUnsupportedMimeType");
+ }
}
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
index 8752fb4..7475e74 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -18,8 +18,11 @@
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.AppModeFull;
+
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
import org.junit.After;
import org.junit.Before;
@@ -30,6 +33,7 @@
* Runs the ScopedStorageTest tests.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
+@AppModeFull
public class ScopedStorageHostTest extends BaseHostJUnit4Test {
private boolean mIsExternalStorageSetup = false;
@@ -43,6 +47,19 @@
}
+ /**
+ * Runs the given phase of ScopedStorageTest by calling into the device with {@code
+ * --no-isolated-storage} flag.
+ * Throws an exception if the test phase fails.
+ */
+ void runDeviceTestWithDisabledIsolatedStorage(String phase) throws Exception {
+ runDeviceTests(new DeviceTestRunOptions("android.scopedstorage.cts")
+ .setDevice(getDevice())
+ .setTestClassName("android.scopedstorage.cts.ScopedStorageTest")
+ .setTestMethodName(phase)
+ .setDisableIsolatedStorage(true));
+ }
+
String executeShellCommand(String cmd) throws Exception {
return getDevice().executeShellCommand(cmd);
}
@@ -428,6 +445,20 @@
runDeviceTest("testWallpaperApisManageExternalStoragePrivileged");
}
+ @Test
+ public void testNoIsolatedStorageInstrumentationFlag() throws Exception {
+ runDeviceTestWithDisabledIsolatedStorage("testNoIsolatedStorageCanCreateFilesAnywhere");
+ runDeviceTestWithDisabledIsolatedStorage(
+ "testNoIsolatedStorageCantReadWriteOtherAppExternalDir");
+ runDeviceTestWithDisabledIsolatedStorage("testNoIsolatedStorageStorageReaddir");
+ runDeviceTestWithDisabledIsolatedStorage("testNoIsolatedStorageQueryOtherAppsFile");
+
+ // Check that appop is revoked after instrumentation is over.
+ runDeviceTest("testCreateFileInAppExternalDir");
+ runDeviceTest("testCreateFileInOtherAppExternalDir");
+ runDeviceTest("testReadWriteFilesInOtherAppExternalDir");
+ }
+
private void grantPermissions(String... perms) throws Exception {
for (String perm : perms) {
executeShellCommand("pm grant android.scopedstorage.cts " + perm);
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageInstantAppHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageInstantAppHostTest.java
new file mode 100644
index 0000000..c97b41f
--- /dev/null
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageInstantAppHostTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.scopedstorage.cts.host;
+
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.AppModeInstant;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Runs the ScopedStorageTest tests for an instant app.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class ScopedStorageInstantAppHostTest extends BaseHostJUnit4Test {
+ /**
+ * Runs the given phase of Test by calling into the device.
+ * Throws an exception if the test phase fails.
+ */
+ protected void runDeviceTest(String phase) throws Exception {
+ assertTrue(runDeviceTests("android.scopedstorage.cts",
+ "android.scopedstorage.cts.ScopedStorageTest", phase));
+ }
+
+ @Test
+ @AppModeInstant
+ public void testInstantAppsCantAccessExternalStorage() throws Exception {
+ runDeviceTest("testInstantAppsCantAccessExternalStorage");
+ }
+}
diff --git a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
index f700391..2422f3b 100644
--- a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
+++ b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
@@ -33,9 +33,11 @@
import static android.scopedstorage.cts.lib.TestUtils.getContentResolver;
import static android.scopedstorage.cts.lib.TestUtils.getFileOwnerPackageFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getFileRowIdFromDatabase;
+import static android.scopedstorage.cts.lib.TestUtils.getImageContentUri;
import static android.scopedstorage.cts.lib.TestUtils.installApp;
import static android.scopedstorage.cts.lib.TestUtils.listAs;
import static android.scopedstorage.cts.lib.TestUtils.openFileAs;
+import static android.scopedstorage.cts.lib.TestUtils.openWithMediaProvider;
import static android.scopedstorage.cts.lib.TestUtils.pollForExternalStorageState;
import static android.scopedstorage.cts.lib.TestUtils.pollForPermission;
import static android.scopedstorage.cts.lib.TestUtils.setupDefaultDirectories;
@@ -55,11 +57,15 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
import android.scopedstorage.cts.lib.TestUtils;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import android.text.TextUtils;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -78,6 +84,7 @@
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
@@ -700,6 +707,57 @@
}
}
+ /**
+ * b/156717256,b/156336269: Test that MediaProvider doesn't throw error on usage of unsupported
+ * or empty/null MIME type.
+ */
+ @Test
+ public void testInsertWithUnsupportedMimeType() throws Exception {
+ pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /*granted*/ true);
+ pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ true);
+
+ final String IMAGE_FILE_DISPLAY_NAME = "LegacyStorageTest_file_" + NONCE;
+ final File imageFile = new File(TestUtils.getDcimDir(), IMAGE_FILE_DISPLAY_NAME + ".jpg");
+
+ for (String mimeType : new String[] {
+ "image/*", "", null, "foo/bar"
+ }) {
+ Uri uri = null;
+ try {
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
+ if (TextUtils.isEmpty(mimeType)) {
+ values.put(MediaStore.MediaColumns.DISPLAY_NAME, imageFile.getName());
+ } else {
+ values.put(MediaStore.MediaColumns.DISPLAY_NAME, IMAGE_FILE_DISPLAY_NAME);
+ }
+ values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
+
+ uri = getContentResolver().insert(getImageContentUri(), values, Bundle.EMPTY);
+ assertNotNull(uri);
+
+ try (final OutputStream fos = getContentResolver().openOutputStream(uri, "rw")) {
+ fos.write(BYTES_DATA1);
+ }
+
+ // Closing the file should trigger a scan, we still scan again to ensure MIME type
+ // is extracted from file extension
+ assertNotNull(MediaStore.scanFile(getContentResolver(), imageFile));
+
+ final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME,
+ MediaStore.MediaColumns.MIME_TYPE};
+ try (Cursor c = getContentResolver().query(uri, projection, null, null, null)) {
+ assertTrue(c.moveToFirst());
+ assertEquals(c.getCount(), 1);
+ assertEquals(c.getString(0), imageFile.getName());
+ assertTrue("image/jpeg".equalsIgnoreCase(c.getString(1)));
+ }
+ } finally {
+ deleteWithMediaProviderNoThrow(uri);
+ }
+ }
+ }
+
private static void assertCanCreateFile(File file) throws IOException {
if (file.exists()) {
file.delete();
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/Android.bp b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/Android.bp
index 3a5ba59..be2ae44 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/Android.bp
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/Android.bp
@@ -15,6 +15,6 @@
java_library {
name: "cts-scopedstorage-lib",
srcs: ["src/**/*.java"],
- static_libs: ["androidx.test.rules", "cts-install-lib"],
+ static_libs: ["androidx.test.rules", "cts-install-lib", "platform-test-annotations",],
sdk_version: "test_current"
}
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
index f17cbbe..34fbe79 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
@@ -374,7 +374,7 @@
/**
* Returns the content URI for images based on the current storage volume.
*/
- public static Uri getMediaContentUri() {
+ public static Uri getImageContentUri() {
return MediaStore.Images.Media.getContentUri(sStorageVolumeName);
}
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index b434603..8f44bae 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -125,6 +125,7 @@
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.platform.test.annotations.AppModeInstant;
import android.provider.MediaStore;
import android.system.ErrnoException;
import android.system.Os;
@@ -200,8 +201,10 @@
// skips all test cases if FUSE is not active.
assumeTrue(getBoolean("persist.sys.fuse", false));
- pollForExternalStorageState();
- getExternalFilesDir().mkdirs();
+ if (!getContext().getPackageManager().isInstantApp()) {
+ pollForExternalStorageState();
+ getExternalFilesDir().mkdirs();
+ }
}
/**
@@ -1662,8 +1665,7 @@
THIS_PACKAGE_NAME, TEST_APP_A.getPackageName()));
final File otherAppExternalDataFile = new File(otherAppExternalDataDir,
NONMEDIA_FILE_NAME);
- assertThat(createFileAs(TEST_APP_A, otherAppExternalDataFile.getAbsolutePath()))
- .isTrue();
+ assertCreateFilesAs(TEST_APP_A, otherAppExternalDataFile);
// File Manager app gets global access with MANAGE_EXTERNAL_STORAGE permission, however,
// file manager app doesn't have access to other app's external files directory
@@ -1683,6 +1685,41 @@
}
/**
+ * Tests that an instant app can't access external storage.
+ */
+ @Test
+ @AppModeInstant
+ public void testInstantAppsCantAccessExternalStorage() throws Exception {
+ assumeTrue("This test requires that the test runs as an Instant app",
+ getContext().getPackageManager().isInstantApp());
+ assertThat(getContext().getPackageManager().isInstantApp()).isTrue();
+
+ // Can't read ExternalStorageDir
+ assertThat(getExternalStorageDir().list()).isNull();
+
+ // Can't create a top-level direcotry
+ final File topLevelDir = new File(getExternalStorageDir(), TEST_DIRECTORY_NAME);
+ assertThat(topLevelDir.mkdir()).isFalse();
+
+ // Can't create file under root dir
+ final File newTxtFile = new File(getExternalStorageDir(), NONMEDIA_FILE_NAME);
+ assertThrows(IOException.class,
+ () -> { newTxtFile.createNewFile(); });
+
+ // Can't create music file under /MUSIC
+ final File newMusicFile = new File(getMusicDir(), AUDIO_FILE_NAME);
+ assertThrows(IOException.class,
+ () -> { newMusicFile.createNewFile(); });
+
+ // getExternalFilesDir() is not null
+ assertThat(getExternalFilesDir()).isNotNull();
+
+ // Can't read/write app specific dir
+ assertThat(getExternalFilesDir().list()).isNull();
+ assertThat(getExternalFilesDir().exists()).isFalse();
+ }
+
+ /**
* Test that apps can create and delete hidden file.
*/
@Test
@@ -2577,16 +2614,11 @@
*/
@Test
public void testCantSetAttrOtherAppsFile() throws Exception {
- // This path's permission is checked in FuseDaemon (directory/external files dir).
- final File externalFilesPath = new File(getExternalFilesDir(), VIDEO_FILE_NAME);
// This path's permission is checked in MediaProvider (directory/external media dir)
final File externalMediaPath = new File(getExternalMediaDir(), VIDEO_FILE_NAME);
try {
// Create the files
- if (!externalFilesPath.exists()) {
- assertThat(externalFilesPath.createNewFile()).isTrue();
- }
if (!externalMediaPath.exists()) {
assertThat(externalMediaPath.createNewFile()).isTrue();
}
@@ -2596,20 +2628,108 @@
// TEST_APP_A should not be able to setattr to other app's files.
assertWithMessage(
- "setattr on directory/external files path [%s]", externalFilesPath.getPath())
- .that(setAttrAs(TEST_APP_A, externalFilesPath.getPath()))
- .isFalse();
- assertWithMessage(
"setattr on directory/external media path [%s]", externalMediaPath.getPath())
.that(setAttrAs(TEST_APP_A, externalMediaPath.getPath()))
.isFalse();
} finally {
- externalFilesPath.delete();
externalMediaPath.delete();
uninstallAppNoThrow(TEST_APP_A);
}
}
+ @Test
+ public void testNoIsolatedStorageCanCreateFilesAnywhere() throws Exception {
+ final File topLevelPdf = new File(getExternalStorageDir(), NONMEDIA_FILE_NAME);
+ final File musicFileInMovies = new File(getMoviesDir(), AUDIO_FILE_NAME);
+ final File imageFileInDcim = new File(getDcimDir(), IMAGE_FILE_NAME);
+ // Nothing special about this, anyone can create an image file in DCIM
+ assertCanCreateFile(imageFileInDcim);
+ // This is where we see the special powers of MANAGE_EXTERNAL_STORAGE, because it can
+ // create a top level file
+ assertCanCreateFile(topLevelPdf);
+ // It can even create a music file in Pictures
+ assertCanCreateFile(musicFileInMovies);
+ }
+
+ @Test
+ public void testNoIsolatedStorageCantReadWriteOtherAppExternalDir() throws Exception {
+ try {
+ // Install TEST_APP_A with READ_EXTERNAL_STORAGE permission.
+ installAppWithStoragePermissions(TEST_APP_A);
+
+ // Let app A create a file in its data dir
+ final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
+ THIS_PACKAGE_NAME, TEST_APP_A.getPackageName()));
+ final File otherAppExternalDataFile = new File(otherAppExternalDataDir,
+ NONMEDIA_FILE_NAME);
+ assertCreateFilesAs(TEST_APP_A, otherAppExternalDataFile);
+
+ // File Manager app gets global access with MANAGE_EXTERNAL_STORAGE permission, however,
+ // file manager app doesn't have access to other app's external files directory
+ assertThat(canOpen(otherAppExternalDataFile, /* forWrite */ false)).isFalse();
+ assertThat(canOpen(otherAppExternalDataFile, /* forWrite */ true)).isFalse();
+ assertThat(otherAppExternalDataFile.delete()).isFalse();
+
+ assertThat(deleteFileAs(TEST_APP_A, otherAppExternalDataFile.getPath())).isTrue();
+
+ assertThrows(IOException.class,
+ () -> { otherAppExternalDataFile.createNewFile(); });
+
+ } finally {
+ uninstallApp(TEST_APP_A); // Uninstalling deletes external app dirs
+ }
+ }
+
+ @Test
+ public void testNoIsolatedStorageStorageReaddir() throws Exception {
+ final File otherAppPdf = new File(getDownloadDir(), "other" + NONMEDIA_FILE_NAME);
+ final File otherAppImg = new File(getDcimDir(), "other" + IMAGE_FILE_NAME);
+ final File otherAppMusic = new File(getMusicDir(), "other" + AUDIO_FILE_NAME);
+ final File otherTopLevelFile = new File(getExternalStorageDir(),
+ "other" + NONMEDIA_FILE_NAME);
+ try {
+ installApp(TEST_APP_A);
+ assertCreateFilesAs(TEST_APP_A, otherAppImg, otherAppMusic, otherAppPdf);
+ executeShellCommand("touch " + otherTopLevelFile);
+
+ // We can list other apps' files
+ assertDirectoryContains(otherAppPdf.getParentFile(), otherAppPdf);
+ assertDirectoryContains(otherAppImg.getParentFile(), otherAppImg);
+ assertDirectoryContains(otherAppMusic.getParentFile(), otherAppMusic);
+ // We can list top level files
+ assertDirectoryContains(getExternalStorageDir(), otherTopLevelFile);
+
+ // We can also list all top level directories
+ assertDirectoryContains(getExternalStorageDir(), getDefaultTopLevelDirs());
+ } finally {
+ executeShellCommand("rm " + otherTopLevelFile);
+ deleteFilesAs(TEST_APP_A, otherAppImg, otherAppMusic, otherAppPdf);
+ uninstallApp(TEST_APP_A);
+ }
+ }
+
+ @Test
+ public void testNoIsolatedStorageQueryOtherAppsFile() throws Exception {
+ final File otherAppPdf = new File(getDownloadDir(), "other" + NONMEDIA_FILE_NAME);
+ final File otherAppImg = new File(getDcimDir(), "other" + IMAGE_FILE_NAME);
+ final File otherAppMusic = new File(getMusicDir(), "other" + AUDIO_FILE_NAME);
+ final File otherHiddenFile = new File(getPicturesDir(), ".otherHiddenFile.jpg");
+ try {
+ installApp(TEST_APP_A);
+ // Apps can't query other app's pending file, hence create file and publish it.
+ assertCreatePublishedFilesAs(
+ TEST_APP_A, otherAppImg, otherAppMusic, otherAppPdf, otherHiddenFile);
+
+ assertCanQueryAndOpenFile(otherAppPdf, "rw");
+ assertCanQueryAndOpenFile(otherAppImg, "rw");
+ assertCanQueryAndOpenFile(otherAppMusic, "rw");
+ assertCanQueryAndOpenFile(otherHiddenFile, "rw");
+ } finally {
+ deleteFilesAs(TEST_APP_A, otherAppImg, otherAppMusic, otherAppPdf, otherHiddenFile);
+ uninstallApp(TEST_APP_A);
+ }
+ }
+
/**
* Checks restrictions for opening pending and trashed files by different apps. Assumes that
* given {@code testApp} is already installed and has READ_EXTERNAL_STORAGE permission. This
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/memutils.c b/hostsidetests/securitybulletin/securityPatch/includes/memutils.c
index 650d2f6..65e1e90 100644
--- a/hostsidetests/securitybulletin/securityPatch/includes/memutils.c
+++ b/hostsidetests/securitybulletin/securityPatch/includes/memutils.c
@@ -61,6 +61,7 @@
if (NULL == real_memalign) {
return;
}
+#ifndef DISABLE_MALLOC_OVERLOADING
real_calloc = dlsym(RTLD_NEXT, "calloc");
if (NULL == real_calloc) {
return;
@@ -73,6 +74,7 @@
if (NULL == real_realloc) {
return;
}
+#endif /* DISABLE_MALLOC_OVERLOADING */
real_free = dlsym(RTLD_NEXT, "free");
if (NULL == real_free) {
return;
@@ -99,14 +101,6 @@
size_t num_pages;
size_t page_size = getpagesize();
- /* User specified alignment is not respected and is overridden by
- * "new_alignment". This is required to catch OOB read when read offset is
- * less than user specified alignment. "new_alignment" is derived based on
- * size_t, and helps to avoid bus errors due to non-aligned memory.
- * "new_alignment", whenever used, is checked to ensure sizeof(size_t)
- * has returned proper value */
- size_t new_alignment = sizeof(size_t);
-
if (s_mem_map_index == MAX_ENTRIES) {
return real_memalign(alignment, size);
}
@@ -115,13 +109,16 @@
return real_memalign(alignment, size);
}
- if ((0 == page_size) || (0 == alignment) || (0 == size)
- || (0 == new_alignment)) {
+ if ((0 == page_size) || (0 == alignment) || (0 == size)) {
return real_memalign(alignment, size);
}
#ifdef CHECK_OVERFLOW
- if (0 != (size % new_alignment)) {
- aligned_size = size + (new_alignment - (size % new_alignment));
+ /* User specified alignment is not respected and is overridden by
+ * MINIMUM_ALIGNMENT. This is required to catch OOB read when read offset
+ * is less than user specified alignment. "MINIMUM_ALIGNMENT" helps to
+ * avoid bus errors due to non-aligned memory. */
+ if (0 != (size % MINIMUM_ALIGNMENT)) {
+ aligned_size = size + (MINIMUM_ALIGNMENT - (size % MINIMUM_ALIGNMENT));
}
#endif
@@ -134,11 +131,7 @@
total_size = (num_pages * page_size);
start_ptr = (char *) real_memalign(page_size, total_size);
#ifdef CHECK_OVERFLOW
-#ifdef FORCE_UNALIGN
- mem_ptr = (char *) start_ptr + ((num_pages - 1) * page_size) - size;
-#else
mem_ptr = (char *) start_ptr + ((num_pages - 1) * page_size) - aligned_size;
-#endif /* FORCE_UNALIGN */
DISABLE_MEM_ACCESS((start_ptr + ((num_pages - 1) * page_size)), page_size);
#endif /* CHECK_OVERFLOW */
#ifdef CHECK_UNDERFLOW
@@ -154,6 +147,7 @@
return mem_ptr;
}
+#ifndef DISABLE_MALLOC_OVERLOADING
void *malloc(size_t size) {
if (s_memutils_initialized == 0) {
memutils_init();
@@ -163,7 +157,7 @@
return real_malloc(size);
}
#endif /* ENABLE_SELECTIVE_OVERLOADING */
- return memalign(sizeof(size_t), size);
+ return memalign(MINIMUM_ALIGNMENT, size);
}
void *calloc(size_t nitems, size_t size) {
@@ -210,6 +204,7 @@
}
return real_realloc(ptr, size);
}
+#endif /* DISABLE_MALLOC_OVERLOADING */
void free(void *ptr) {
if (s_memutils_initialized == 0) {
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/memutils.h b/hostsidetests/securitybulletin/securityPatch/includes/memutils.h
index 10ee31e..4d3791e 100644
--- a/hostsidetests/securitybulletin/securityPatch/includes/memutils.h
+++ b/hostsidetests/securitybulletin/securityPatch/includes/memutils.h
@@ -19,6 +19,7 @@
#endif /* __cplusplus */
#define MAX_ENTRIES (1024 * 1024)
#define INITIAL_VAL (0xBE)
+#define MINIMUM_ALIGNMENT (16)
#define DISABLE_MEM_ACCESS(mem, size)\
mprotect((char *) mem, size, PROT_NONE);
@@ -43,9 +44,11 @@
} map_struct_t;
static void* (*real_memalign)(size_t, size_t) = NULL;
+#ifndef DISABLE_MALLOC_OVERLOADING
static void* (*real_calloc)(size_t, size_t) = NULL;
static void* (*real_malloc)(size_t) = NULL;
static void* (*real_realloc)(void *ptr, size_t size) = NULL;
+#endif /* DISABLE_MALLOC_OVERLOADING */
static void (*real_free)(void *) = NULL;
static int s_memutils_initialized = 0;
static int s_mem_map_index = 0;
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h
index 8986c32..aeea4a0 100644
--- a/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h
+++ b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h
@@ -34,7 +34,7 @@
#include <android/IOMXBufferSource.h>
#include <media/omx/1.0/WOmx.h>
#include <binder/MemoryDealer.h>
-#include "HardwareAPI.h"
+#include "media/hardware/HardwareAPI.h"
#include "OMX_Component.h"
#include <binder/ProcessState.h>
#include <media/stagefright/foundation/ALooper.h>
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 a7922db..93064e6 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
@@ -331,6 +331,15 @@
}
@Test
+ public void testStageAnotherSessionImmediatelyAfterAbandonMultiPackage() throws Exception {
+ assertThat(getInstalledVersion(TestApp.Apex)).isEqualTo(1);
+ int sessionId = stageMultipleApks(TestApp.Apex2, TestApp.A1, TestApp.B1)
+ .assertSuccessful().getSessionId();
+ abandonSession(sessionId);
+ stageSingleApk(TestApp.Apex2).assertSuccessful();
+ }
+
+ @Test
public void testNoSessionUpdatedBroadcastSentForStagedSessionAbandon() throws Exception {
assertThat(getInstalledVersion(TestApp.A)).isEqualTo(-1);
assertThat(getInstalledVersion(TestApp.Apex)).isEqualTo(1);
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 3345f62..427dbcc 100644
--- a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
@@ -138,6 +138,12 @@
}
@Test
+ public void testStageAnotherSessionImmediatelyAfterAbandonMultiPackage() throws Exception {
+ assumeTrue("Device does not support updating APEX", isUpdatingApexSupported());
+ runPhase("testStageAnotherSessionImmediatelyAfterAbandonMultiPackage");
+ }
+
+ @Test
public void testNoSessionUpdatedBroadcastSentForStagedSessionAbandon() throws Exception {
assumeTrue("Device does not support updating APEX", isUpdatingApexSupported());
runPhase("testNoSessionUpdatedBroadcastSentForStagedSessionAbandon");
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 9311656..144e28e 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
@@ -200,6 +200,7 @@
// Op 96 was deprecated/removed
APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, 97);
APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUTO_REVOKE_MANAGED_BY_INSTALLER, 98);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_NO_ISOLATED_STORAGE, 99);
}
@Test
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTests.java b/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTests.java
index 4c0e4e6..7ad2d17 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTests.java
@@ -76,6 +76,7 @@
Thread.sleep(10);
}
doAppBreadcrumbReportedStart(/* irrelevant val */ 6); // Event, after TTL_TIME_SEC secs.
+ Thread.sleep(WAIT_TIME_SHORT);
report = getStatsdStatsReport();
LogUtil.CLog.d("got following statsdstats report: " + report.toString());
foundActiveConfig = false;
diff --git a/hostsidetests/systemui/src/android/host/systemui/TvMicrophoneCaptureIndicatorTest.java b/hostsidetests/systemui/src/android/host/systemui/TvMicrophoneCaptureIndicatorTest.java
index c42faa2..674226c 100644
--- a/hostsidetests/systemui/src/android/host/systemui/TvMicrophoneCaptureIndicatorTest.java
+++ b/hostsidetests/systemui/src/android/host/systemui/TvMicrophoneCaptureIndicatorTest.java
@@ -37,12 +37,14 @@
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.After;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
+@Ignore
@RunWith(DeviceJUnit4ClassRunner.class)
public class TvMicrophoneCaptureIndicatorTest extends BaseHostJUnit4Test {
private static final String SHELL_AM_START_FG_SERVICE =
diff --git a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
index c478bf2..ad1fae9 100644
--- a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
+++ b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
@@ -62,6 +62,8 @@
import org.junit.runner.RunWith;
import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;
@@ -85,12 +87,16 @@
private static final long TIMEOUT_BIND_SERVICE_SEC = 2;
+ private static final long TIMEOUT_WAIT_FOR_IDLE_MS = 2_000;
+
// TODO: Make it a @TestApi or move the test using this to a different location.
// Copy of DeviceConfig.NAMESPACE_BLOBSTORE constant
private static final String NAMESPACE_BLOBSTORE = "blobstore";
private static final String KEY_SESSION_EXPIRY_TIMEOUT_MS = "session_expiry_timeout_ms";
private static final String KEY_LEASE_ACQUISITION_WAIT_DURATION_MS =
"lease_acquisition_wait_time_ms";
+ private static final String KEY_DELETE_ON_LAST_LEASE_DELAY_MS =
+ "delete_on_last_lease_delay_ms";
private static final String KEY_TOTAL_BYTES_PER_APP_LIMIT_FLOOR =
"total_bytes_per_app_limit_floor";
public static final String KEY_TOTAL_BYTES_PER_APP_LIMIT_FRACTION =
@@ -206,9 +212,15 @@
blobData.readFromSessionAndVerifyBytes(session,
101 /* offset */, 1001 /* length */);
- blobData.writeToSession(session, 202 /* offset */, 2002 /* length */);
+ blobData.writeToSession(session, 202 /* offset */, 2002 /* length */,
+ blobData.getFileSize());
blobData.readFromSessionAndVerifyBytes(session,
202 /* offset */, 2002 /* length */);
+
+ final CompletableFuture<Integer> callback = new CompletableFuture<>();
+ session.commit(mContext.getMainExecutor(), callback::complete);
+ assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
+ .isEqualTo(0);
}
} finally {
blobData.delete();
@@ -596,6 +608,52 @@
}
@Test
+ public void testSessionCommit_incompleteData() throws Exception {
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
+ blobData.prepare();
+ try {
+ final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
+ assertThat(sessionId).isGreaterThan(0L);
+
+ try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
+ blobData.writeToSession(session, 0, blobData.getFileSize() - 2);
+
+ final CompletableFuture<Integer> callback = new CompletableFuture<>();
+ session.commit(mContext.getMainExecutor(), callback::complete);
+ assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
+ .isEqualTo(1);
+ }
+ } finally {
+ blobData.delete();
+ }
+ }
+
+ @Test
+ public void testSessionCommit_incorrectData() throws Exception {
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
+ blobData.prepare();
+ try {
+ final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
+ assertThat(sessionId).isGreaterThan(0L);
+
+ try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
+ blobData.writeToSession(session, 0, blobData.getFileSize());
+ try (OutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(
+ session.openWrite(0, blobData.getFileSize()))) {
+ out.write("wrong_data".getBytes(StandardCharsets.UTF_8));
+ }
+
+ final CompletableFuture<Integer> callback = new CompletableFuture<>();
+ session.commit(mContext.getMainExecutor(), callback::complete);
+ assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
+ .isEqualTo(1);
+ }
+ } finally {
+ blobData.delete();
+ }
+ }
+
+ @Test
public void testRecommitBlob() throws Exception {
final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
@@ -731,11 +789,13 @@
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(
sessionId)) {
final long partialFileSizeBytes = minSizeMb * 1024L * 1024L;
- blobData.writeToSession(session, 0L, partialFileSizeBytes);
+ blobData.writeToSession(session, 0L, partialFileSizeBytes,
+ blobData.getFileSize());
blobData.readFromSessionAndVerifyBytes(session, 0L,
(int) partialFileSizeBytes);
blobData.writeToSession(session, partialFileSizeBytes,
- blobData.getFileSize() - partialFileSizeBytes);
+ blobData.getFileSize() - partialFileSizeBytes,
+ blobData.getFileSize());
blobData.readFromSessionAndVerifyBytes(session, partialFileSizeBytes,
(int) (blobData.getFileSize() - partialFileSizeBytes));
@@ -875,7 +935,7 @@
}
@Test
- public void testAcquireRelease_deleteImmediately() throws Exception {
+ public void testAcquireRelease_deleteAfterDelay() throws Exception {
final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
final long waitDurationMs = TimeUnit.SECONDS.toMillis(1);
@@ -892,6 +952,10 @@
releaseLease(mContext, blobData.getBlobHandle());
assertNoLeasedBlobs(mBlobStoreManager);
+ SystemClock.sleep(waitDurationMs);
+ SystemUtil.runWithShellPermissionIdentity(() ->
+ mBlobStoreManager.waitForIdle(TIMEOUT_WAIT_FOR_IDLE_MS));
+
assertThrows(SecurityException.class, () -> mBlobStoreManager.acquireLease(
blobData.getBlobHandle(), R.string.test_desc,
blobData.getExpiryTimeMillis()));
@@ -899,7 +963,8 @@
} finally {
blobData.delete();
}
- }, Pair.create(KEY_LEASE_ACQUISITION_WAIT_DURATION_MS, String.valueOf(waitDurationMs)));
+ }, Pair.create(KEY_LEASE_ACQUISITION_WAIT_DURATION_MS, String.valueOf(waitDurationMs)),
+ Pair.create(KEY_DELETE_ON_LAST_LEASE_DELAY_MS, String.valueOf(waitDurationMs)));
}
@Test
@@ -941,7 +1006,7 @@
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session, 0, partialFileSize);
+ blobData.writeToSession(session, 0, partialFileSize, partialFileSize);
}
StorageStats afterStatsForPkg = storageStatsManager
@@ -958,7 +1023,8 @@
// Complete writing data.
final long totalFileSize = blobData.getFileSize();
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session, partialFileSize, totalFileSize - partialFileSize);
+ blobData.writeToSession(session, partialFileSize, totalFileSize - partialFileSize,
+ totalFileSize);
}
afterStatsForPkg = storageStatsManager
@@ -974,7 +1040,8 @@
// Commit the session.
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session, partialFileSize, session.getSize() - partialFileSize);
+ blobData.writeToSession(session, partialFileSize,
+ session.getSize() - partialFileSize, blobData.getFileSize());
final CompletableFuture<Integer> callback = new CompletableFuture<>();
session.commit(mContext.getMainExecutor(), callback::complete);
assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
@@ -1232,7 +1299,7 @@
assertThat(sessionId).isGreaterThan(0L);
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session, 0, partialFileSize);
+ blobData.writeToSession(session, 0, partialFileSize, blobData.getFileSize());
}
SystemClock.sleep(waitDurationMs);
@@ -1242,7 +1309,7 @@
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
blobData.writeToSession(session, partialFileSize,
- blobData.getFileSize() - partialFileSize);
+ blobData.getFileSize() - partialFileSize, blobData.getFileSize());
final CompletableFuture<Integer> callback = new CompletableFuture<>();
session.commit(mContext.getMainExecutor(), callback::complete);
assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
@@ -1278,7 +1345,7 @@
assertThat(sessionId).isGreaterThan(0L);
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session, 0, 100);
+ blobData.writeToSession(session, 0, 100, blobData.getFileSize());
}
SystemClock.sleep(waitDurationMs);
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java
index 3551205..e75d109 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java
@@ -168,7 +168,8 @@
private boolean isCarModeSupported() {
// TVs don't support car mode.
return !getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_LEANBACK_ONLY);
+ PackageManager.FEATURE_LEANBACK_ONLY)
+ && !getContext().getSystemService(UiModeManager.class).isUiModeLocked();
}
/**
@@ -305,7 +306,6 @@
if (!isCarModeSupported()) {
return;
}
-
runIdleJobStartsOnlyWhenIdle();
setCarMode(true);
@@ -314,6 +314,9 @@
}
public void testIdleJobStartsOnlyWhenIdle_screenEndsIdle() throws Exception {
+ if (!isCarModeSupported()) {
+ return;
+ }
runIdleJobStartsOnlyWhenIdle();
toggleScreenOn(true);
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index c065b1e..e013454 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.app.AppOpsManager;
@@ -102,6 +103,7 @@
private boolean mInitialAirplaneModeState;
private String mInitialJobSchedulerConstants;
private String mInitialDisplayTimeout;
+ private boolean mAutomotiveDevice;
private TestAppInterface mTestAppInterface;
@@ -162,6 +164,15 @@
mInitialDisplayTimeout =
Settings.System.getString(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT);
Settings.System.putString(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, "300000");
+
+ // In automotive device, always-on screen and endless battery charging are assumed.
+ mAutomotiveDevice =
+ mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ if (mAutomotiveDevice) {
+ setScreenState(true);
+ // TODO(b/159176758): make sure that initial power supply is on.
+ BatteryUtils.runDumpsysBatterySetPluggedIn(true);
+ }
}
@Test
@@ -281,6 +292,7 @@
@Test
public void testJobsInRestrictedBucket_ParoleSession() throws Exception {
assumeTrue("app standby not enabled", mAppStandbyEnabled);
+ assumeFalse("not testable in automotive device", mAutomotiveDevice);
// Disable coalescing
Settings.Global.putString(mContext.getContentResolver(),
@@ -304,6 +316,7 @@
@Test
public void testJobsInRestrictedBucket_NoRequiredNetwork() throws Exception {
assumeTrue("app standby not enabled", mAppStandbyEnabled);
+ assumeFalse("not testable in automotive device", mAutomotiveDevice);
// Disable coalescing and the parole session
Settings.Global.putString(mContext.getContentResolver(),
@@ -339,6 +352,7 @@
@Test
public void testJobsInRestrictedBucket_WithRequiredNetwork() throws Exception {
assumeTrue("app standby not enabled", mAppStandbyEnabled);
+ assumeFalse("not testable in automotive device", mAutomotiveDevice);
assumeTrue(mHasWifi);
ensureSavedWifiNetwork(mWifiManager);
@@ -386,6 +400,7 @@
@Test
public void testJobsInNeverApp() throws Exception {
assumeTrue("app standby not enabled", mAppStandbyEnabled);
+ assumeFalse("not testable in automotive device", mAutomotiveDevice);
BatteryUtils.runDumpsysBatteryUnplug();
setTestPackageStandbyBucket(Bucket.NEVER);
@@ -396,6 +411,8 @@
@Test
public void testUidActiveBypassesStandby() throws Exception {
+ assumeFalse("not testable in automotive device", mAutomotiveDevice);
+
BatteryUtils.runDumpsysBatteryUnplug();
setTestPackageStandbyBucket(Bucket.NEVER);
tempWhitelistTestApp(6_000);
@@ -407,6 +424,7 @@
@Test
public void testBatterySaverOff() throws Exception {
+ assumeFalse("not testable in automotive device", mAutomotiveDevice);
BatteryUtils.assumeBatterySaverFeature();
BatteryUtils.runDumpsysBatteryUnplug();
@@ -418,6 +436,7 @@
@Test
public void testBatterySaverOn() throws Exception {
+ assumeFalse("not testable in automotive device", mAutomotiveDevice);
BatteryUtils.assumeBatterySaverFeature();
BatteryUtils.runDumpsysBatteryUnplug();
@@ -429,6 +448,7 @@
@Test
public void testUidActiveBypassesBatterySaverOn() throws Exception {
+ assumeFalse("not testable in automotive device", mAutomotiveDevice);
BatteryUtils.assumeBatterySaverFeature();
BatteryUtils.runDumpsysBatteryUnplug();
@@ -441,6 +461,7 @@
@Test
public void testBatterySaverOnThenUidActive() throws Exception {
+ assumeFalse("not testable in automotive device", mAutomotiveDevice);
BatteryUtils.assumeBatterySaverFeature();
// Enable battery saver, and schedule a job. It shouldn't run.
diff --git a/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java b/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
index 776879d..a3e6256 100644
--- a/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
@@ -431,7 +431,7 @@
int width = size.getWidth();
int height = size.getHeight();
/**
- * Check the input allocation is sane.
+ * Check the input allocation is valid.
* - Byte size matches what we expect.
* - The input is not all zeroes.
*/
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 4a4aa0d..90a7dcd 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -2361,7 +2361,7 @@
result.get(CaptureResult.TONEMAP_PRESET_CURVE));
}
- // Tonemap curve result availability and basic sanity check for all modes.
+ // Tonemap curve result availability and basic validity check for all modes.
mCollector.expectValuesInRange("Tonemap curve red values are out of range",
CameraTestUtils.toObject(mapRed), /*min*/ZERO, /*max*/ONE);
mCollector.expectInRange("Tonemap curve red length is out of range",
@@ -2999,8 +2999,9 @@
*/
private void changeExposure(CaptureRequest.Builder requestBuilder,
long expTime, int sensitivity) {
- // Check if the max analog sensitivity is available and no larger than max sensitivity.
- // The max analog sensitivity is not actually used here. This is only an extra sanity check.
+ // Check if the max analog sensitivity is available and no larger than max sensitivity. The
+ // max analog sensitivity is not actually used here. This is only an extra correctness
+ // check.
mStaticInfo.getMaxAnalogSensitivityChecked();
expTime = mStaticInfo.getExposureClampToRange(expTime);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index 07155ff..7bf1f4c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -2084,7 +2084,7 @@
}
/**
- * Sanity check of optical black regions.
+ * Correctness check of optical black regions.
*/
@Test
public void testOpticalBlackRegions() {
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
index 99c6b33..6cfa435 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
@@ -187,7 +187,7 @@
texture.setDefaultBufferSize(640, 480);
Surface surface = new Surface(texture);
- // Make sure that the default newInstance is still sane.
+ // Make sure that the default newInstance is still valid.
ImageWriter defaultWriter = ImageWriter.newInstance(surface, MAX_NUM_IMAGES);
Image defaultImage = defaultWriter.dequeueInputImage();
defaultWriter.close();
diff --git a/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
index 4a88c84..56c2652 100644
--- a/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
@@ -92,7 +92,6 @@
private static final double FRAME_DURATION_THRESHOLD = 0.03;
private static final double FOV_THRESHOLD = 0.03;
- private static final double ASPECT_RATIO_THRESHOLD = 0.03;
private static final long MAX_TIMESTAMP_DIFFERENCE_THRESHOLD = 10000000; // 10ms
private StateWaiter mSessionWaiter;
@@ -994,51 +993,56 @@
}
/**
- * Validate that physical cameras' crop region are compensated based on focal length.
+ * Validate that physical cameras are not cropping too much.
*
- * This is to make sure physical processed streams have the same field of view as long as
- * the physical cameras supports it.
+ * This is to make sure physical processed streams have at least the same field of view as
+ * the logical stream, or the maximum field of view of the physical camera, whichever is
+ * smaller.
+ *
+ * Note that the FOV is calculated in the directio of sensor width.
*/
private void validatePhysicalCamerasFov(TotalCaptureResult totalCaptureResult,
List<String> physicalCameraIds) {
Rect cropRegion = totalCaptureResult.get(CaptureResult.SCALER_CROP_REGION);
Float focalLength = totalCaptureResult.get(CaptureResult.LENS_FOCAL_LENGTH);
- float cropAspectRatio = (float)cropRegion.width() / cropRegion.height();
+ Float zoomRatio = totalCaptureResult.get(CaptureResult.CONTROL_ZOOM_RATIO);
+ Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
+ SizeF sensorSize = mStaticInfo.getValueFromKeyNonNull(
+ CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);
// Assume subject distance >> focal length, and subject distance >> camera baseline.
- float fov = cropRegion.width() / (2 * focalLength);
+ double fov = 2 * Math.toDegrees(Math.atan2(sensorSize.getWidth() * cropRegion.width() /
+ (2 * zoomRatio * activeArraySize.width()), focalLength));
+
Map<String, CaptureResult> physicalResultsDual =
totalCaptureResult.getPhysicalCameraResults();
for (String physicalId : physicalCameraIds) {
+ StaticMetadata physicalStaticInfo = mAllStaticInfo.get(physicalId);
CaptureResult physicalResult = physicalResultsDual.get(physicalId);
Rect physicalCropRegion = physicalResult.get(CaptureResult.SCALER_CROP_REGION);
- final Float physicalFocalLength = physicalResult.get(CaptureResult.LENS_FOCAL_LENGTH);
+ Float physicalFocalLength = physicalResult.get(CaptureResult.LENS_FOCAL_LENGTH);
+ Float physicalZoomRatio = physicalResult.get(CaptureResult.CONTROL_ZOOM_RATIO);
+ Rect physicalActiveArraySize = physicalStaticInfo.getActiveArraySizeChecked();
+ SizeF physicalSensorSize = mStaticInfo.getValueFromKeyNonNull(
+ CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);
- StaticMetadata staticInfo = mAllStaticInfo.get(physicalId);
- final Rect activeArraySize = staticInfo.getActiveArraySizeChecked();
- final Float maxDigitalZoom = staticInfo.getAvailableMaxDigitalZoomChecked();
- int maxWidth = activeArraySize.width();
- int minWidth = (int)(activeArraySize.width() / maxDigitalZoom);
- int expectedCropWidth = Math.max(Math.min(Math.round(fov * 2 * physicalFocalLength),
- maxWidth), minWidth);
+ double physicalFov = 2 * Math.toDegrees(Math.atan2(
+ physicalSensorSize.getWidth() * physicalCropRegion.width() /
+ (2 * physicalZoomRatio * physicalActiveArraySize.width()), physicalFocalLength));
- // Makes sure FOV matches to the maximum extent.
- assertTrue("Physical stream FOV (Field of view) should match logical stream to most "
- + "extent. Crop region actual width " + physicalCropRegion.width() +
- " vs expected width " + expectedCropWidth,
- Math.abs((float)physicalCropRegion.width() - expectedCropWidth) /
- expectedCropWidth < FOV_THRESHOLD);
+ double maxPhysicalFov = 2 * Math.toDegrees(Math.atan2(physicalSensorSize.getWidth() / 2,
+ physicalFocalLength));
+ double expectedPhysicalFov = Math.min(maxPhysicalFov, fov);
- // Makes sure aspect ratio matches.
- float physicalCropAspectRatio =
- (float)physicalCropRegion.width() / physicalCropRegion.height();
- assertTrue("Physical stream for camera " + physicalId + " aspect ratio " +
- physicalCropAspectRatio + " should match logical streams aspect ratio " +
- cropAspectRatio, Math.abs(physicalCropAspectRatio - cropAspectRatio) <
- ASPECT_RATIO_THRESHOLD);
+ if (VERBOSE) {
+ Log.v(TAG, "Logical camera Fov: " + fov + ", maxPhyiscalFov: " + maxPhysicalFov +
+ ", physicalFov: " + physicalFov);
+ }
+ assertTrue("Physical stream FOV (Field of view) should be greater or equal to"
+ + " min(logical stream FOV, max physical stream FOV). Physical FOV: "
+ + physicalFov + " vs min(" + fov + ", " + maxPhysicalFov,
+ physicalFov - expectedPhysicalFov > -FOV_THRESHOLD);
}
-
-
}
/**
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index 067104c..bf42ab7 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -2046,7 +2046,7 @@
}
/**
- * Validate video snapshot capture image object sanity and test.
+ * Validate video snapshot capture image object validity and test.
*
* <p> Check for size, format and jpeg decoding</p>
*
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index 80a2fe95..0a24671 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -1829,7 +1829,7 @@
{ LEGACY_COMBINATIONS, LIMITED_COMBINATIONS, BURST_COMBINATIONS, FULL_COMBINATIONS,
RAW_COMBINATIONS, LEVEL_3_COMBINATIONS };
- sanityCheckConfigurationTables(TABLES);
+ validityCheckConfigurationTables(TABLES);
for (String id : mCameraIdsUnderTest) {
openDevice(id);
@@ -1965,7 +1965,7 @@
final int[][][] TABLES =
{ LIMITED_COMBINATIONS, FULL_COMBINATIONS, RAW_COMBINATIONS, LEVEL_3_COMBINATIONS };
- sanityCheckConfigurationTables(TABLES);
+ validityCheckConfigurationTables(TABLES);
for (String id : mCameraIdsUnderTest) {
openDevice(id);
@@ -2091,9 +2091,9 @@
}
/**
- * Sanity check the configuration tables.
+ * Verify correctness of the configuration tables.
*/
- private void sanityCheckConfigurationTables(final int[][][] tables) throws Exception {
+ private void validityCheckConfigurationTables(final int[][][] tables) throws Exception {
int tableIdx = 0;
for (int[][] table : tables) {
int rowIdx = 0;
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index 991649e..5f2f961 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -1564,9 +1564,9 @@
}
/**
- * Validate JPEG capture image object sanity and test.
+ * Validate JPEG capture image object correctness and test.
* <p>
- * In addition to image object sanity, this function also does the decoding
+ * In addition to image object correctness, this function also does the decoding
* test, which is slower.
* </p>
*
diff --git a/tests/camera/src/android/hardware/cts/CameraTest.java b/tests/camera/src/android/hardware/cts/CameraTest.java
index e7b36f0..c2645ad 100644
--- a/tests/camera/src/android/hardware/cts/CameraTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraTest.java
@@ -1045,9 +1045,9 @@
}
/**
- * Sanity check of some extra exif tags.
+ * Correctness check of some extra exif tags.
* <p>
- * Sanity check some extra exif tags without asserting the check failures
+ * Check some extra exif tags without asserting the check failures
* immediately. When a failure is detected, the failure cause is logged,
* the rest of the tests are still executed. The caller can assert with the
* failure cause based on the returned test status.
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index 9561eb0..ad0ed57 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -395,7 +395,7 @@
image = reader.acquireNextImage();
} finally {
if (image != null) {
- // Should only do some quick sanity check in callback, as the ImageReader
+ // Should only do some quick validity checks in callback, as the ImageReader
// could be closed asynchronously, which will close all images acquired from
// this ImageReader.
checkImage(image, mSize.getWidth(), mSize.getHeight(), mFormat);
@@ -2443,7 +2443,7 @@
/**
* Simple validation of JPEG image size and format.
* <p>
- * Only validate the image object sanity. It is fast, but doesn't actually
+ * Only validate the image object basic correctness. It is fast, but doesn't actually
* check the buffer data. Assert is used here as it make no sense to
* continue the test if the jpeg image captured has some serious failures.
* </p>
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/Preconditions.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/Preconditions.java
index cb9e522..bef3e26 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/Preconditions.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/Preconditions.java
@@ -22,7 +22,7 @@
/**
* Helper set of methods to perform precondition checks before starting method execution.
*
- * <p>Typically used to sanity check arguments or the current object state.</p>
+ * <p>Typically used to validity check arguments or the current object state.</p>
*/
public final class Preconditions {
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index 332964c..a05af2a 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -518,7 +518,7 @@
}
/**
- * Get max AE regions and do sanity check.
+ * Get max AE regions and do validity check.
*
* @return AE max regions supported by the camera device
*/
@@ -531,7 +531,7 @@
}
/**
- * Get max AWB regions and do sanity check.
+ * Get max AWB regions and do validity check.
*
* @return AWB max regions supported by the camera device
*/
@@ -544,7 +544,7 @@
}
/**
- * Get max AF regions and do sanity check.
+ * Get max AF regions and do validity check.
*
* @return AF max regions supported by the camera device
*/
@@ -628,7 +628,7 @@
}
/**
- * Get available thumbnail sizes and do the sanity check.
+ * Get available thumbnail sizes and do the validity check.
*
* @return The array of available thumbnail sizes
*/
@@ -656,7 +656,7 @@
}
/**
- * Get available focal lengths and do the sanity check.
+ * Get available focal lengths and do the validity check.
*
* @return The array of available focal lengths
*/
@@ -677,7 +677,7 @@
}
/**
- * Get available apertures and do the sanity check.
+ * Get available apertures and do the validity check.
*
* @return The non-null array of available apertures
*/
@@ -992,7 +992,7 @@
}
/**
- * Get hyperfocalDistance and do the sanity check.
+ * Get hyperfocalDistance and do the validity check.
* <p>
* Note that, this tag is optional, will return -1 if this tag is not
* available.
@@ -1151,7 +1151,7 @@
}
/**
- * get android.control.availableModes and do the sanity check.
+ * get android.control.availableModes and do the validity check.
*
* @return available control modes.
*/
@@ -1207,7 +1207,7 @@
}
/**
- * Get aeAvailableModes and do the sanity check.
+ * Get aeAvailableModes and do the validity check.
*
* <p>Depending on the check level this class has, for WAR or COLLECT levels,
* If the aeMode list is invalid, return an empty mode array. The the caller doesn't
@@ -1277,7 +1277,7 @@
}
/**
- * Get available AWB modes and do the sanity check.
+ * Get available AWB modes and do the validity check.
*
* @return array that contains available AWB modes, empty array if awbAvailableModes is
* unavailable.
@@ -1303,7 +1303,7 @@
}
/**
- * Get available AF modes and do the sanity check.
+ * Get available AF modes and do the validity check.
*
* @return array that contains available AF modes, empty array if afAvailableModes is
* unavailable.
@@ -1691,7 +1691,7 @@
}
/**
- * Get value of key android.control.aeCompensationStep and do the sanity check.
+ * Get value of key android.control.aeCompensationStep and do the validity check.
*
* @return default value if the value is null.
*/
@@ -1716,7 +1716,7 @@
}
/**
- * Get value of key android.control.aeCompensationRange and do the sanity check.
+ * Get value of key android.control.aeCompensationRange and do the validity check.
*
* @return default value if the value is null or malformed.
*/
@@ -1746,7 +1746,7 @@
}
/**
- * Get availableVideoStabilizationModes and do the sanity check.
+ * Get availableVideoStabilizationModes and do the validity check.
*
* @return available video stabilization modes, empty array if it is unavailable.
*/
@@ -1777,7 +1777,7 @@
}
/**
- * Get availableOpticalStabilization and do the sanity check.
+ * Get availableOpticalStabilization and do the validity check.
*
* @return available optical stabilization modes, empty array if it is unavailable.
*/
@@ -1967,7 +1967,7 @@
}
/**
- * Get max pipeline depth and do the sanity check.
+ * Get max pipeline depth and do the validity check.
*
* @return max pipeline depth, default value if it is not available.
*/
@@ -2033,7 +2033,7 @@
/**
- * Get available capabilities and do the sanity check.
+ * Get available capabilities and do the validity check.
*
* @return reported available capabilities list, empty list if the value is unavailable.
*/
@@ -2299,7 +2299,7 @@
}
/**
- * Get max number of output raw streams and do the basic sanity check.
+ * Get max number of output raw streams and do the basic validity check.
*
* @return reported max number of raw output stream
*/
@@ -2312,7 +2312,7 @@
}
/**
- * Get max number of output processed streams and do the basic sanity check.
+ * Get max number of output processed streams and do the basic validity check.
*
* @return reported max number of processed output stream
*/
@@ -2325,7 +2325,7 @@
}
/**
- * Get max number of output stalling processed streams and do the basic sanity check.
+ * Get max number of output stalling processed streams and do the basic validity check.
*
* @return reported max number of stalling processed output stream
*/
@@ -2338,7 +2338,7 @@
}
/**
- * Get lens facing and do the sanity check
+ * Get lens facing and do the validity check
* @return lens facing, return default value (BACK) if value is unavailable.
*/
public int getLensFacingChecked() {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index e005059..859eb29 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -64,12 +64,10 @@
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
-import android.provider.Settings;
import android.server.wm.CommandSession.ActivitySession;
import android.server.wm.CommandSession.ConfigInfo;
import android.server.wm.CommandSession.SizeInfo;
import android.server.wm.TestJournalProvider.TestJournalContainer;
-import android.server.wm.settings.SettingsSession;
import android.view.Display;
import org.junit.Test;
@@ -452,10 +450,9 @@
public void testRotatedInfoWithFixedRotationTransform() {
assumeTrue("Skipping test: no rotation support", supportsRotation());
- // TODO(b/143053092): Remove the settings if it becomes stable.
- mObjectTracker.manage(new SettingsSession<>(
- Settings.Global.getUriFor("fixed_rotation_transform"),
- Settings.Global::getInt, Settings.Global::putInt)).set(1);
+ // Start a portrait activity first to ensure that the orientation will change.
+ launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
+ mWmState.waitForLastOrientation(SCREEN_ORIENTATION_PORTRAIT);
getLaunchActivityBuilder()
.setUseInstrumentation()
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
index 0f89ea2..267bec9 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
@@ -25,7 +25,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
import static android.server.wm.ComponentNameUtils.getActivityName;
-import static android.server.wm.UiDeviceUtils.pressBackButton;
+import static android.server.wm.UiDeviceUtils.pressHomeButton;
import static android.server.wm.app.Components.ANIMATION_TEST_ACTIVITY;
import static android.server.wm.app.Components.ASSISTANT_ACTIVITY;
import static android.server.wm.app.Components.ASSISTANT_VOICE_INTERACTION_SERVICE;
@@ -172,11 +172,22 @@
TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, expectedWindowingMode);
}
- mWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
- mWmState.assertFrontStack("Fullscreen stack should be on top.",
- expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
- mWmState.assertFocusedStack("Fullscreen stack should be focused.",
- expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
+ if (isAssistantOnTop()) {
+ // If the assistant is configured to be always-on-top, then the new task should have
+ // been started behind it and the assistant stack should still be on top.
+ mWmState.assertFocusedActivity(
+ "AssistantActivity should be focused", ASSISTANT_ACTIVITY);
+ mWmState.assertFrontStackActivityType(
+ "Assistant stack should be on top.", ACTIVITY_TYPE_ASSISTANT);
+ mWmState.assertFocusedStack("Assistant stack should be focused.",
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
+ } else {
+ mWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
+ mWmState.assertFrontStack("Fullscreen stack should be on top.",
+ expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
+ mWmState.assertFocusedStack("Fullscreen stack should be focused.",
+ expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
+ }
// Now, tell it to finish itself and ensure that the assistant stack is brought back forward
mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
@@ -189,6 +200,13 @@
@Test
public void testAssistantStackFinishToPreviousApp() throws Exception {
+ // If the Assistant is configured to be always-on-top, then the assistant activity
+ // started in setUp() will not allow any other activities to start. Therefore we should
+ // remove it before launching a fullscreen activity.
+ if (isAssistantOnTop()) {
+ removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
+ }
+
// Launch an assistant activity on top of an existing fullscreen activity, and ensure that
// the fullscreen activity is still visible and on top after the assistant activity finishes
launchActivityOnDisplay(TEST_ACTIVITY, mAssistantDisplayId);
@@ -232,7 +250,8 @@
// Go home, launch the assistant and check to see that home is visible
removeStacksInWindowingModes(WINDOWING_MODE_FULLSCREEN,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- launchHomeActivity();
+ pressHomeButton();
+ resumeAppSwitches();
launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
EXTRA_ASSISTANT_IS_TRANSLUCENT, "true");
waitForValidStateWithActivityType(
@@ -257,7 +276,8 @@
// Go home, launch assistant, launch app into fullscreen with activity present, and go
// back.Ensure home is visible.
removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
- launchHomeActivity();
+ pressHomeButton();
+ resumeAppSwitches();
launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
EXTRA_ASSISTANT_IS_TRANSLUCENT, "true",
EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY));
@@ -266,7 +286,7 @@
final ComponentName homeActivity = mWmState.getHomeActivityName();
mWmState.waitAndAssertVisibilityGone(homeActivity);
- pressBackButton();
+ mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
mWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
assertAssistantStackExists();
mWmState.waitForHomeActivityVisible();
@@ -319,7 +339,7 @@
launchActivityOnDisplay(ANIMATION_TEST_ACTIVITY, mAssistantDisplayId);
// Wait for animation finished.
mWmState.waitForActivityState(ANIMATION_TEST_ACTIVITY, STATE_RESUMED);
- mWmState.assertVisibility(ASSISTANT_ACTIVITY, false);
+ mWmState.assertVisibility(ASSISTANT_ACTIVITY, isAssistantOnTop());
// Launch the assistant again and ensure that it goes into the same task
launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION,
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index 042eb48..72ce477 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -1004,6 +1004,8 @@
@Test
@FlakyTest(bugId=156314330)
public void testFinishPipActivityWithTaskOverlay() throws Exception {
+ // Trigger PiP menu activity to properly lose focuse when going home
+ launchActivity(TEST_ACTIVITY);
// Launch PiP activity
launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
waitForEnterPip(PIP_ACTIVITY);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlTest.java b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlTest.java
index 00fc83b..e3566b9 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlTest.java
@@ -178,18 +178,23 @@
*/
@Test
public void testReparentOff() throws Throwable {
+ final SurfaceControl sc = buildDefaultRedSurface(null);
verifyTest(
new SurfaceControlTestCase.ParentSurfaceConsumer () {
@Override
public void addChildren(SurfaceControl parent) {
- final SurfaceControl sc = buildDefaultRedSurface(parent);
-
+ new SurfaceControl.Transaction().reparent(sc, parent).apply();
new SurfaceControl.Transaction().reparent(sc, null).apply();
-
- sc.release();
}
},
new RectChecker(new Rect(0, 0, 100, 100), PixelColor.WHITE));
+ // Since the SurfaceControl is parented off-screen, if we release our reference
+ // it may completely die. If this occurs while the render thread is still rendering
+ // the RED background we could trigger a crash. For this test defer destroying the
+ // Surface until we have collected our test results.
+ if (sc != null) {
+ sc.release();
+ }
}
/**
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
index 6299fc8..1972122 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
@@ -19,13 +19,16 @@
import static android.server.wm.WindowInsetsAnimationControllerTests.ControlListener.Event.CANCELLED;
import static android.server.wm.WindowInsetsAnimationControllerTests.ControlListener.Event.FINISHED;
import static android.server.wm.WindowInsetsAnimationControllerTests.ControlListener.Event.READY;
-import static android.server.wm.WindowInsetsAnimationTestBase.showImeWithHardKeyboardSetting;
import static android.server.wm.WindowInsetsAnimationUtils.INSETS_EVALUATOR;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.cts.mockime.ImeEventStreamTestUtils.editorMatcher;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
@@ -33,14 +36,17 @@
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeThat;
import static org.junit.Assume.assumeTrue;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.app.Instrumentation;
import android.graphics.Insets;
import android.os.CancellationSignal;
import android.platform.test.annotations.Presubmit;
@@ -60,6 +66,10 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.cts.mockime.ImeEventStream;
+import com.android.cts.mockime.ImeSettings;
+import com.android.cts.mockime.MockImeSession;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -85,7 +95,7 @@
* Build/Install/Run:
* atest CtsWindowManagerDeviceTestCases:WindowInsetsAnimationControllerTests
*/
-//TODO(b/159038873) @Presubmit
+@Presubmit
@RunWith(Parameterized.class)
public class WindowInsetsAnimationControllerTests extends WindowManagerTestBase {
@@ -102,6 +112,13 @@
@Rule
public LimitedErrorCollector mErrorCollector = new LimitedErrorCollector();
+ /**
+ * {@link MockImeSession} used when {@link #mType} is
+ * {@link android.view.WindowInsets.Type#ime()}.
+ */
+ @Nullable
+ private MockImeSession mMockImeSession;
+
@Parameter(0)
public int mType;
@@ -120,15 +137,41 @@
@Before
public void setUp() throws Exception {
super.setUp();
+ final ImeEventStream mockImeEventStream;
+ if (mType == ime()) {
+ final Instrumentation instrumentation = getInstrumentation();
+ assumeThat(MockImeSession.getUnavailabilityReason(instrumentation.getContext()),
+ nullValue());
+
+ // For the best test stability MockIme should be selected before launching TestActivity.
+ mMockImeSession = MockImeSession.create(
+ instrumentation.getContext(), instrumentation.getUiAutomation(),
+ new ImeSettings.Builder());
+ mockImeEventStream = mMockImeSession.openEventStream();
+ } else {
+ mockImeEventStream = null;
+ }
+
mActivity = startActivity(TestActivity.class);
mRootView = mActivity.getWindow().getDecorView();
mListener = new ControlListener(mErrorCollector);
- showImeWithHardKeyboardSetting(mObjectTracker);
assumeTestCompatibility();
+
+ if (mockImeEventStream != null) {
+ // TestActivity has a focused EditText. Hence MockIme should receive onStartInput() for
+ // that EditText within a reasonable time.
+ expectEvent(mockImeEventStream,
+ editorMatcher("onStartInput", mActivity.getEditTextMarker()),
+ TimeUnit.SECONDS.toMillis(10));
+ }
}
@After
public void tearDown() throws Throwable {
+ if (mMockImeSession != null) {
+ mMockImeSession.close();
+ mMockImeSession = null;
+ }
runOnUiThread(() -> {}); // Fence to make sure we dispatched everything.
mCallbacks.forEach(VerifyingCallback::assertNoRunningAnimations);
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
index 32255d2..187ed91 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
@@ -56,11 +56,13 @@
@Presubmit
public class WindowInsetsAnimationImeTests extends WindowInsetsAnimationTestBase {
+ private static final int KEYBOARD_HEIGHT = 400;
+
@Rule
public final MockImeSessionRule mMockImeSessionRule = new MockImeSessionRule(
InstrumentationRegistry.getInstrumentation().getContext(),
InstrumentationRegistry.getInstrumentation().getUiAutomation(),
- new ImeSettings.Builder()
+ new ImeSettings.Builder().setInputViewHeight(KEYBOARD_HEIGHT).setDrawsBehindNavBar(true)
);
@Before
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
index 3494c7c..af8ed0b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
@@ -35,9 +35,8 @@
import static org.mockito.Mockito.spy;
import android.os.Bundle;
-import android.provider.Settings;
+import android.os.SystemClock;
import android.server.wm.WindowInsetsAnimationTestBase.AnimCallback.AnimationStep;
-import android.server.wm.settings.SettingsSession;
import android.util.ArraySet;
import android.view.View;
import android.view.WindowInsets;
@@ -46,6 +45,8 @@
import android.widget.LinearLayout;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+
import org.junit.Assert;
import org.mockito.InOrder;
@@ -157,23 +158,6 @@
}
}
- /**
- * Workaround for b/158637229: force the keyboard to show even when there is a hardware keyboard
- * during IME related insets tests to avoid issues when testing on devices that have a hardware
- * keyboard.
- *
- * @param tracker the test's {@link ObjectTracker}, used to clean up the setting override after
- * the test finishes.
- */
- static void showImeWithHardKeyboardSetting(ObjectTracker tracker) {
- final SettingsSession<Integer> showImeWithHardKeyboardSetting = new SettingsSession<>(
- Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD),
- Settings.Secure::getInt,
- Settings.Secure::putInt);
- tracker.manage(showImeWithHardKeyboardSetting);
- showImeWithHardKeyboardSetting.set(1);
- }
-
public static class AnimCallback extends WindowInsetsAnimation.Callback {
public static class AnimationStep {
@@ -301,6 +285,10 @@
public static class TestActivity extends FocusableActivity {
+ private final String mEditTextMarker =
+ "android.server.wm.WindowInsetsAnimationTestBase.TestActivity"
+ + SystemClock.elapsedRealtimeNanos();
+
AnimCallback mCallback =
spy(new AnimCallback(WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP));
WindowInsets mLastWindowInsets;
@@ -319,6 +307,11 @@
}
}
+ @NonNull
+ String getEditTextMarker() {
+ return mEditTextMarker;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -328,6 +321,7 @@
mView.setOnApplyWindowInsetsListener(mListener);
mChild = new TextView(this);
mEditor = new EditText(this);
+ mEditor.setPrivateImeOptions(mEditTextMarker);
mView.addView(mChild);
mView.addView(mEditor);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
index 55fa3d2..aca3a97 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
@@ -17,7 +17,6 @@
package android.server.wm;
import static android.graphics.PixelFormat.TRANSLUCENT;
-import static android.server.wm.WindowInsetsAnimationTestBase.showImeWithHardKeyboardSetting;
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE;
@@ -35,13 +34,19 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.editorMatcher;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
+
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeThat;
import static org.junit.Assume.assumeTrue;
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.Instrumentation;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
@@ -57,10 +62,14 @@
import android.widget.LinearLayout;
import android.widget.TextView;
+import androidx.annotation.Nullable;
import androidx.test.filters.FlakyTest;
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.SystemUtil;
+import com.android.cts.mockime.ImeEventStream;
+import com.android.cts.mockime.ImeSettings;
+import com.android.cts.mockime.MockImeSession;
import org.junit.Rule;
import org.junit.Test;
@@ -181,20 +190,27 @@
}
@Test
- @FlakyTest(detail = "b/159038873")
- public void testImeShowAndHide() {
- showImeWithHardKeyboardSetting(mObjectTracker);
+ public void testImeShowAndHide() throws Exception {
+ final Instrumentation instrumentation = getInstrumentation();
+ assumeThat(MockImeSession.getUnavailabilityReason(instrumentation.getContext()),
+ nullValue());
+ try (MockImeSession imeSession = MockImeSession.create(instrumentation.getContext(),
+ instrumentation.getUiAutomation(), new ImeSettings.Builder())) {
+ final ImeEventStream stream = imeSession.openEventStream();
- final TestActivity activity = startActivity(TestActivity.class);
- final View rootView = activity.getWindow().getDecorView();
- getInstrumentation().runOnMainSync(() -> {
- rootView.getWindowInsetsController().show(ime());
- });
- PollingCheck.waitFor(TIMEOUT, () -> rootView.getRootWindowInsets().isVisible(ime()));
- getInstrumentation().runOnMainSync(() -> {
- rootView.getWindowInsetsController().hide(ime());
- });
- PollingCheck.waitFor(TIMEOUT, () -> !rootView.getRootWindowInsets().isVisible(ime()));
+ final TestActivity activity = startActivity(TestActivity.class);
+ expectEvent(stream, editorMatcher("onStartInput", activity.mEditTextMarker), TIMEOUT);
+
+ final View rootView = activity.getWindow().getDecorView();
+ getInstrumentation().runOnMainSync(() -> {
+ rootView.getWindowInsetsController().show(ime());
+ });
+ PollingCheck.waitFor(TIMEOUT, () -> rootView.getRootWindowInsets().isVisible(ime()));
+ getInstrumentation().runOnMainSync(() -> {
+ rootView.getWindowInsetsController().hide(ime());
+ });
+ PollingCheck.waitFor(TIMEOUT, () -> !rootView.getRootWindowInsets().isVisible(ime()));
+ }
}
@Test
@@ -463,15 +479,18 @@
}
@Test
- @FlakyTest(detail = "b/159038873")
public void testShowImeOnCreate() throws Exception {
- showImeWithHardKeyboardSetting(mObjectTracker);
-
- final TestShowOnCreateActivity activity = startActivity(TestShowOnCreateActivity.class);
- final View rootView = activity.getWindow().getDecorView();
- ANIMATION_CALLBACK.waitForFinishing(TIMEOUT);
- PollingCheck.waitFor(TIMEOUT,
- () -> rootView.getRootWindowInsets().isVisible(ime()));
+ final Instrumentation instrumentation = getInstrumentation();
+ assumeThat(MockImeSession.getUnavailabilityReason(instrumentation.getContext()),
+ nullValue());
+ try (MockImeSession imeSession = MockImeSession.create(instrumentation.getContext(),
+ instrumentation.getUiAutomation(), new ImeSettings.Builder())) {
+ final TestShowOnCreateActivity activity = startActivity(TestShowOnCreateActivity.class);
+ final View rootView = activity.getWindow().getDecorView();
+ ANIMATION_CALLBACK.waitForFinishing(TIMEOUT);
+ PollingCheck.waitFor(TIMEOUT,
+ () -> rootView.getRootWindowInsets().isVisible(ime()));
+ }
}
@Test
@@ -619,10 +638,11 @@
}
}
- private static View setViews(Activity activity) {
+ private static View setViews(Activity activity, @Nullable String privateImeOptions) {
LinearLayout layout = new LinearLayout(activity);
View text = new TextView(activity);
EditText editor = new EditText(activity);
+ editor.setPrivateImeOptions(privateImeOptions);
layout.addView(text);
layout.addView(editor);
activity.setContentView(layout);
@@ -631,11 +651,13 @@
}
public static class TestActivity extends FocusableActivity {
+ final String mEditTextMarker =
+ getClass().getName() + "/" + SystemClock.elapsedRealtimeNanos();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setViews(this);
+ setViews(this, mEditTextMarker);
getWindow().setSoftInputMode(SOFT_INPUT_STATE_HIDDEN);
}
}
@@ -645,7 +667,7 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- View layout = setViews(this);
+ View layout = setViews(this, null /* privateImeOptions */);
ANIMATION_CALLBACK.reset();
getWindow().getDecorView().setWindowInsetsAnimationCallback(ANIMATION_CALLBACK);
getWindow().getInsetsController().hide(statusBars());
@@ -654,11 +676,10 @@
}
public static class TestShowOnCreateActivity extends FocusableActivity {
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- View layout = setViews(this);
+ setViews(this, null /* privateImeOptions */);
ANIMATION_CALLBACK.reset();
getWindow().getDecorView().setWindowInsetsAnimationCallback(ANIMATION_CALLBACK);
getWindow().getInsetsController().show(ime());
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index 77391b9..7ddc020 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -215,6 +215,7 @@
private static Boolean sHasHomeScreen = null;
private static Boolean sSupportsSystemDecorsOnSecondaryDisplays = null;
private static Boolean sSupportsInsecureLockScreen = null;
+ private static Boolean sIsAssistantOnTop = null;
private static boolean sStackTaskLeakFound;
protected static final int INVALID_DEVICE_ROTATION = -1;
@@ -1092,6 +1093,14 @@
return sSupportsInsecureLockScreen;
}
+ protected boolean isAssistantOnTop() {
+ if (sIsAssistantOnTop == null) {
+ sIsAssistantOnTop = mContext.getResources().getBoolean(
+ android.R.bool.config_assistantOnTopOfDream);
+ }
+ return sIsAssistantOnTop;
+ }
+
/**
* Rotation support is indicated by explicitly having both landscape and portrait
* features or not listing either at all.
diff --git a/tests/sensor/src/android/hardware/cts/helpers/SensorStats.java b/tests/sensor/src/android/hardware/cts/helpers/SensorStats.java
index 3ef2eef..c6b247b 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/SensorStats.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/SensorStats.java
@@ -40,6 +40,7 @@
* together so that they form a tree.
*/
public class SensorStats {
+ private static final String TAG = "SensorStats";
public static final String DELIMITER = "__";
public static final String ERROR = "error";
@@ -146,23 +147,39 @@
}
}
+ /* Checks if external storage is available for read and write */
+ private boolean isExternalStorageWritable() {
+ String state = Environment.getExternalStorageState();
+ return Environment.MEDIA_MOUNTED.equals(state);
+ }
+
/**
* Utility method to log the stats to a file. Will overwrite the file if it already exists.
*/
public void logToFile(Context context, String fileName) throws IOException {
- // Only log to file if currently not an Instant App since Instant Apps do not have access to
- // external storage.
- if (!context.getPackageManager().isInstantApp()) {
- File statsDirectory = SensorCtsHelper.getSensorTestDataDirectory("stats/");
- File logFile = new File(statsDirectory, fileName);
- final Map<String, Object> flattened = flatten();
- FileWriter fileWriter = new FileWriter(logFile, false /* append */);
- try (BufferedWriter writer = new BufferedWriter(fileWriter)) {
- for (String key : getSortedKeys(flattened)) {
- Object value = flattened.get(key);
- writer.write(String.format("%s: %s\n", key, getValueString(value)));
+ if (!isExternalStorageWritable()) {
+ Log.w(TAG,
+ "External storage unavailable, skipping log to file: " + fileName);
+ return;
+ }
+
+ try {
+ // Only log to file if currently not an Instant App since Instant Apps do not have access to
+ // external storage.
+ if (!context.getPackageManager().isInstantApp()) {
+ File statsDirectory = SensorCtsHelper.getSensorTestDataDirectory("stats/");
+ File logFile = new File(statsDirectory, fileName);
+ final Map<String, Object> flattened = flatten();
+ FileWriter fileWriter = new FileWriter(logFile, false /* append */);
+ try (BufferedWriter writer = new BufferedWriter(fileWriter)) {
+ for (String key : getSortedKeys(flattened)) {
+ Object value = flattened.get(key);
+ writer.write(String.format("%s: %s\n", key, getValueString(value)));
+ }
}
}
+ } catch(IOException e) {
+ Log.w(TAG, "Unable to write to file: " + fileName, e);
}
}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 4440010..92e351a 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -105,14 +105,11 @@
private static final String APPOPS_SET_SHELL_COMMAND = "appops set {0} " +
AppOpsManager.OPSTR_GET_USAGE_STATS + " {1}";
- private static final String USAGE_SOURCE_GET_SHELL_COMMAND = "settings get global " +
- Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE;
+ private static final String GET_SHELL_COMMAND = "settings get global ";
- private static final String USAGE_SOURCE_SET_SHELL_COMMAND = "settings put global " +
- Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE + " {0}";
+ private static final String SET_SHELL_COMMAND = "settings put global ";
- private static final String USAGE_SOURCE_DELETE_SHELL_COMMAND = "settings delete global " +
- Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE;
+ private static final String DELETE_SHELL_COMMAND = "settings delete global ";
private static final String TEST_APP_PKG = "android.app.usage.cts.test1";
private static final String TEST_APP_CLASS = "android.app.usage.cts.test1.SomeActivity";
@@ -139,6 +136,7 @@
private KeyguardManager mKeyguardManager;
private String mTargetPackage;
private String mCachedUsageSourceSetting;
+ private String mCachedEnableRestrictedBucketSetting;
@Before
public void setUp() throws Exception {
@@ -152,16 +150,18 @@
assumeTrue("App Standby not enabled on device", AppStandbyUtils.isAppStandbyEnabled());
setAppOpsMode("allow");
- mCachedUsageSourceSetting = getUsageSourceSetting();
+ mCachedUsageSourceSetting = getSetting(Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE);
+ mCachedEnableRestrictedBucketSetting = getSetting(Settings.Global.ENABLE_RESTRICTED_BUCKET);
}
@After
public void cleanUp() throws Exception {
if (mCachedUsageSourceSetting != null &&
- !mCachedUsageSourceSetting.equals(getUsageSourceSetting())) {
+ !mCachedUsageSourceSetting.equals(
+ getSetting(Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE))) {
setUsageSourceSetting(mCachedUsageSourceSetting);
- mUsageStatsManager.forceUsageSourceSettingRead();
}
+ setSetting(Settings.Global.ENABLE_RESTRICTED_BUCKET, mCachedEnableRestrictedBucketSetting);
// Force stop test package to avoid any running test code from carrying over to the next run
SystemUtil.runWithShellPermissionIdentity(() -> mAm.forceStopPackage(TEST_APP_PKG));
mUiDevice.pressHome();
@@ -179,16 +179,20 @@
executeShellCmd(MessageFormat.format(APPOPS_SET_SHELL_COMMAND, mTargetPackage, mode));
}
- private String getUsageSourceSetting() throws Exception {
- return executeShellCmd(USAGE_SOURCE_GET_SHELL_COMMAND);
+ private String getSetting(String name) throws Exception {
+ return executeShellCmd(GET_SHELL_COMMAND + name);
}
- private void setUsageSourceSetting(String usageSource) throws Exception {
- if (usageSource.equals("null")) {
- executeShellCmd(USAGE_SOURCE_DELETE_SHELL_COMMAND);
+ private void setSetting(String name, String setting) throws Exception {
+ if (setting == null || setting.equals("null")) {
+ executeShellCmd(DELETE_SHELL_COMMAND + name);
} else {
- executeShellCmd(MessageFormat.format(USAGE_SOURCE_SET_SHELL_COMMAND, usageSource));
+ executeShellCmd(SET_SHELL_COMMAND + name + " " + setting);
}
+ }
+
+ private void setUsageSourceSetting(String value) throws Exception {
+ setSetting(Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE, value);
mUsageStatsManager.forceUsageSourceSettingRead();
}
@@ -683,7 +687,9 @@
// TODO(148887416): get this test to work for instant apps
@AppModeFull(reason = "Test APK Activity not found when installed as an instant app")
@Test
- public void testUserForceIntoRestricted() throws IOException {
+ public void testUserForceIntoRestricted() throws Exception {
+ setSetting(Settings.Global.ENABLE_RESTRICTED_BUCKET, "1");
+
launchSubActivity(TaskRootActivity.class);
assertEquals("Activity launch didn't bring app up to ACTIVE bucket",
UsageStatsManager.STANDBY_BUCKET_ACTIVE,
@@ -700,7 +706,28 @@
// TODO(148887416): get this test to work for instant apps
@AppModeFull(reason = "Test APK Activity not found when installed as an instant app")
@Test
- public void testUserLaunchRemovesFromRestricted() throws IOException {
+ public void testUserForceIntoRestricted_BucketDisabled() throws Exception {
+ setSetting(Settings.Global.ENABLE_RESTRICTED_BUCKET, "0");
+
+ launchSubActivity(TaskRootActivity.class);
+ assertEquals("Activity launch didn't bring app up to ACTIVE bucket",
+ UsageStatsManager.STANDBY_BUCKET_ACTIVE,
+ mUsageStatsManager.getAppStandbyBucket(mTargetPackage));
+
+ // User force shouldn't have to deal with the timeout.
+ setStandByBucket(mTargetPackage, "restricted");
+ assertNotEquals("User was able to force into RESTRICTED bucket when bucket disabled",
+ UsageStatsManager.STANDBY_BUCKET_RESTRICTED,
+ mUsageStatsManager.getAppStandbyBucket(mTargetPackage));
+
+ }
+
+ // TODO(148887416): get this test to work for instant apps
+ @AppModeFull(reason = "Test APK Activity not found when installed as an instant app")
+ @Test
+ public void testUserLaunchRemovesFromRestricted() throws Exception {
+ setSetting(Settings.Global.ENABLE_RESTRICTED_BUCKET, "1");
+
setStandByBucket(mTargetPackage, "restricted");
assertEquals("User was unable to force an app into RESTRICTED bucket",
UsageStatsManager.STANDBY_BUCKET_RESTRICTED,
@@ -712,6 +739,26 @@
mUsageStatsManager.getAppStandbyBucket(mTargetPackage));
}
+ /** Confirm the default value of {@link Settings.Global.ENABLE_RESTRICTED_BUCKET}. */
+ // TODO(148887416): get this test to work for instant apps
+ @AppModeFull(reason = "Test APK Activity not found when installed as an instant app")
+ @Test
+ public void testDefaultEnableRestrictedBucketOff() throws Exception {
+ setSetting(Settings.Global.ENABLE_RESTRICTED_BUCKET, null);
+
+ launchSubActivity(TaskRootActivity.class);
+ assertEquals("Activity launch didn't bring app up to ACTIVE bucket",
+ UsageStatsManager.STANDBY_BUCKET_ACTIVE,
+ mUsageStatsManager.getAppStandbyBucket(mTargetPackage));
+
+ // User force shouldn't have to deal with the timeout.
+ setStandByBucket(mTargetPackage, "restricted");
+ assertNotEquals("User was able to force into RESTRICTED bucket when bucket disabled",
+ UsageStatsManager.STANDBY_BUCKET_RESTRICTED,
+ mUsageStatsManager.getAppStandbyBucket(mTargetPackage));
+
+ }
+
// TODO(148887416): get this test to work for instant apps
@AppModeFull(reason = "Test APK Activity not found when installed as an instant app")
@Test
diff --git a/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AppOpsUserService.kt b/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AppOpsUserService.kt
index 832eb49..100b9af 100644
--- a/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AppOpsUserService.kt
+++ b/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AppOpsUserService.kt
@@ -107,10 +107,10 @@
setNotedAppOpsCollector()
- assertThat(asyncNoted).isEmpty()
+ assertThat(noted).isEmpty()
assertThat(selfNoted).isEmpty()
eventually {
- assertThat(noted.map { it.first.op }).containsExactly(OPSTR_COARSE_LOCATION)
+ assertThat(asyncNoted.map { it.op }).containsExactly(OPSTR_COARSE_LOCATION)
}
}
}
diff --git a/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AutoClosingActivity.kt b/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AutoClosingActivity.kt
index 222059f..3dd5c21 100644
--- a/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AutoClosingActivity.kt
+++ b/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AutoClosingActivity.kt
@@ -21,6 +21,8 @@
class AutoClosingActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
finish()
}
}
diff --git a/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt b/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt
index 1d14a77..9f785b8 100644
--- a/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt
@@ -29,7 +29,6 @@
private const val APK_PATH = "/data/local/tmp/cts/appops/"
private const val APP_PKG = "android.app.appops.cts.apptocollect"
-private const val MESSAGE = "Stack trace message"
@AppModeFull(reason = "Test relies on seeing other apps. Instant apps can't see other apps")
class RuntimeMessageCollectionTest {
@@ -58,7 +57,7 @@
val start = System.currentTimeMillis()
runWithShellPermissionIdentity {
appOpsManager.noteOp(AppOpsManager.OPSTR_READ_CONTACTS, appUid, APP_PKG,
- TEST_ATTRIBUTION_TAG, MESSAGE)
+ TEST_ATTRIBUTION_TAG, null)
}
while (System.currentTimeMillis() - start < TIMEOUT_MILLIS) {
sleep(200)
@@ -71,7 +70,7 @@
assertThat(message.op).isEqualTo(AppOpsManager.OPSTR_READ_CONTACTS)
assertThat(message.uid).isEqualTo(appUid)
assertThat(message.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
- assertThat(message.message).isEqualTo(MESSAGE)
+ assertThat(message.message).isNotNull()
return
}
}
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
index ec02cd3..75f7cc4 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
@@ -38,7 +38,6 @@
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -234,7 +233,6 @@
@LargeTest
@Test
- @Ignore("Flaky, b/159368388 to reenable.")
public void testInstallSysTrace() throws Exception {
// Async atrace dump uses less resources but requires periodic pulls.
// Overall timeout of 30secs in 100ms intervals should be enough.
@@ -270,8 +268,11 @@
});
readFromProcess.start();
- installPackage(TEST_APK);
- assertTrue(isAppInstalled(TEST_APP_PACKAGE));
+ for (int i = 0; i < 3; ++i) {
+ installPackage(TEST_APK);
+ assertTrue(isAppInstalled(TEST_APP_PACKAGE));
+ uninstallPackageSilently(TEST_APP_PACKAGE);
+ }
readFromProcess.join();
assertNotEquals(0, result.size());
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
index 7e29288..2333601 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
@@ -44,7 +44,7 @@
(WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
mMetrics = new DisplayMetrics();
- display.getMetrics(mMetrics);
+ display.getRealMetrics(mMetrics);
}
@Presubmit
diff --git a/tests/tests/media/libmediandkjni/Android.bp b/tests/tests/media/libmediandkjni/Android.bp
index e501daa..becae52 100644
--- a/tests/tests/media/libmediandkjni/Android.bp
+++ b/tests/tests/media/libmediandkjni/Android.bp
@@ -46,7 +46,6 @@
"native-media-jni.cpp",
"native_media_utils.cpp",
"native_media_decoder_source.cpp",
- "native_media_encoder_jni.cpp",
],
include_dirs: ["system/core/include"],
shared_libs: [
diff --git a/tests/tests/media/libmediandkjni/native_media_encoder_jni.cpp b/tests/tests/media/libmediandkjni/native_media_encoder_jni.cpp
deleted file mode 100644
index 2333ddd..0000000
--- a/tests/tests/media/libmediandkjni/native_media_encoder_jni.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "NativeMediaEnc"
-
-#include <stddef.h>
-#include <inttypes.h>
-#include <log/log.h>
-
-#include <assert.h>
-#include <jni.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <semaphore.h>
-#include <list>
-#include <memory>
-#include <string>
-
-#include <android/native_window_jni.h>
-
-#include "media/NdkMediaFormat.h"
-#include "media/NdkMediaExtractor.h"
-#include "media/NdkMediaCodec.h"
-#include "media/NdkMediaCrypto.h"
-#include "media/NdkMediaFormat.h"
-#include "media/NdkMediaMuxer.h"
-
-#include "native_media_source.h"
-using namespace Utils;
-
-class NativeEncoder : Thread {
-public:
-
- NativeEncoder(const std::string&);
- NativeEncoder(const NativeEncoder&) = delete;
- ~NativeEncoder();
- static std::shared_ptr<ANativeWindow> getPersistentSurface();
- std::shared_ptr<ANativeWindow> getSurface() const;
-
- Status prepare(std::unique_ptr<RunConfig> config, std::shared_ptr<ANativeWindow> anw = nullptr);
- Status start();
- Status waitForCompletion();
- Status validate();
-
- Status reset();
-
-protected:
- void run() override;
-
-private:
- std::shared_ptr<AMediaCodec> mEnc;
- std::shared_ptr<ANativeWindow> mLocalSurface; // the one created by createInputSurface()
- std::string mOutFileName;
- bool mStarted;
-
- Stats mStats;
- std::unique_ptr<RunConfig> mRunConfig;
-
-};
-
-NativeEncoder::NativeEncoder(const std::string& outFileName)
- : mEnc(nullptr),
- mLocalSurface(nullptr),
- mOutFileName(outFileName),
- mStarted(false) {
- mRunConfig = nullptr;
-}
-
-NativeEncoder::~NativeEncoder() {
- mEnc = nullptr;
- mLocalSurface = nullptr;
- mRunConfig = nullptr;
-}
-
-//static
-std::shared_ptr<ANativeWindow> NativeEncoder::getPersistentSurface() {
- ANativeWindow *ps;
- media_status_t ret = AMediaCodec_createPersistentInputSurface(&ps);
- if (ret != AMEDIA_OK) {
- ALOGE("Failed to create persistent surface !");
- return nullptr;
- }
- ALOGI("Encoder: created persistent surface %p", ps);
- return std::shared_ptr<ANativeWindow>(ps, deleter_ANativeWindow);
-}
-
-std::shared_ptr<ANativeWindow> NativeEncoder::getSurface() const {
- return mLocalSurface;
-}
-
-Status NativeEncoder::prepare(
- std::unique_ptr<RunConfig> runConfig, std::shared_ptr<ANativeWindow> surface) {
- assert(runConfig != nullptr);
- assert(runConfig->format() != nullptr);
-
- ALOGI("NativeEncoder::prepare");
- mRunConfig = std::move(runConfig);
-
- AMediaFormat *config = mRunConfig->format();
- ALOGI("Encoder format: %s", AMediaFormat_toString(config));
-
- const char *mime;
- AMediaFormat_getString(config, AMEDIAFORMAT_KEY_MIME, &mime);
-
- AMediaCodec *enc = AMediaCodec_createEncoderByType(mime);
- mEnc = std::shared_ptr<AMediaCodec>(enc, deleter_AMediaCodec);
-
- media_status_t status = AMediaCodec_configure(
- mEnc.get(), config, NULL, NULL /* crypto */, AMEDIACODEC_CONFIGURE_FLAG_ENCODE);
- if (status != AMEDIA_OK) {
- ALOGE("failed to configure encoder");
- return FAIL;
- }
-
- if (surface == nullptr) {
- ANativeWindow *anw;
- status = AMediaCodec_createInputSurface(mEnc.get(), &anw);
- mLocalSurface = std::shared_ptr<ANativeWindow>(anw, deleter_ANativeWindow);
- ALOGI("created input surface = %p", mLocalSurface.get());
- } else {
- ALOGI("setting persistent input surface %p", surface.get());
- status = AMediaCodec_setInputSurface(mEnc.get(), surface.get());
- }
-
- return status == AMEDIA_OK ? OK : FAIL;
-}
-
-Status NativeEncoder::start() {
- ALOGI("starting encoder..");
-
- media_status_t status = AMediaCodec_start(mEnc.get());
- if (status != AMEDIA_OK) {
- ALOGE("failed to start decoder");
- return FAIL;
- }
- if (startThread() != OK) {
- return FAIL;
- }
- mStarted = true;
- return OK;
-}
-
-Status NativeEncoder::waitForCompletion() {
- joinThread();
- ALOGI("encoder done..");
- return OK;
-}
-
-Status NativeEncoder::validate() {
- const char *s = AMediaFormat_toString(mRunConfig->format());
- ALOGI("RESULT: Encoder Output Format: %s", s);
-
- {
- int32_t encodedFrames = mStats.frameCount();
- int32_t inputFrames = mRunConfig->frameCount();
- ALOGI("RESULT: input frames = %d, Encoded frames = %d",
- inputFrames, encodedFrames);
- if (encodedFrames != inputFrames) {
- ALOGE("RESULT: ERROR: output frame count does not match input");
- return FAIL;
- }
- }
-
- if (Validator::checkOverallBitrate(mStats, *mRunConfig) != OK) {
- ALOGE("Overall bitrate check failed!");
- return FAIL;
- }
- if (Validator::checkIntraPeriod(mStats, *mRunConfig) != OK) {
- ALOGE("I-period check failed!");
- return FAIL;
- }
- if (Validator::checkDynamicKeyFrames(mStats, *mRunConfig) != OK) {
- ALOGE("Dynamic-I-frame-request check failed!");
- return FAIL;
- }
- if (Validator::checkDynamicBitrate(mStats, *mRunConfig) != OK) {
- ALOGE("Dynamic-bitrate-update check failed!");
- return FAIL;
- }
-
- return OK;
-}
-
-Status NativeEncoder::reset() {
-
- mEnc = nullptr;
- return OK;
-}
-
-void NativeEncoder::run() {
-
- assert(mRunConfig != nullptr);
-
- int32_t framesToEncode = mRunConfig->frameCount();
- auto dynamicParams = mRunConfig->dynamicParams();
- auto paramItr = dynamicParams.begin();
- int32_t nFrameCount = 0;
-
- while (nFrameCount < framesToEncode) {
- // apply frame-specific settings
- for (;paramItr != dynamicParams.end()
- && (*paramItr)->frameNum() <= nFrameCount; ++paramItr) {
- DParamRef& p = *paramItr;
- if (p->frameNum() == nFrameCount) {
- assert(p->param() != nullptr);
- const char *s = AMediaFormat_toString(p->param());
- ALOGI("Encoder DynamicParam @frame[%d] - applying setting : %s",
- nFrameCount, s);
- AMediaCodec_setParameters(mEnc.get(), p->param());
- }
- }
-
- AMediaCodecBufferInfo info;
- int status = AMediaCodec_dequeueOutputBuffer(mEnc.get(), &info, 5000000);
- if (status >= 0) {
- ALOGV("got encoded buffer[%d] of size=%d @%lld us flags=%x",
- nFrameCount, info.size, (long long)info.presentationTimeUs, info.flags);
- mStats.add(info);
- AMediaCodec_releaseOutputBuffer(mEnc.get(), status, false);
- ++nFrameCount;
-
- if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
- ALOGV("saw EOS");
- break;
- }
-
- } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
- } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
- std::shared_ptr<AMediaFormat> format = std::shared_ptr<AMediaFormat>(
- AMediaCodec_getOutputFormat(mEnc.get()), deleter_AMediaFormat);
- mStats.setOutputFormat(format);
- ALOGV("format changed: %s", AMediaFormat_toString(format.get()));
- } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
- ALOGE("no frame in 5 seconds, assume stuck");
- break;
- } else {
- ALOGV("Invalid status : %d", status);
- }
- }
-
- ALOGV("Encoder exited !");
- AMediaCodec_stop(mEnc.get());
-}
-
-static std::shared_ptr<AMediaFormat> createMediaFormat(
- std::string mime,
- int32_t w, int32_t h, int32_t colorFormat,
- int32_t bitrate, float framerate,
- int32_t i_interval) {
-
- std::shared_ptr<AMediaFormat> config(AMediaFormat_new(), deleter_AMediaFormat);
-
- AMediaFormat_setString(config.get(), AMEDIAFORMAT_KEY_MIME, mime.c_str());
- AMediaFormat_setInt32(config.get(), AMEDIAFORMAT_KEY_WIDTH, w);
- AMediaFormat_setInt32(config.get(), AMEDIAFORMAT_KEY_HEIGHT, h);
- AMediaFormat_setFloat(config.get(), AMEDIAFORMAT_KEY_FRAME_RATE, framerate);
- AMediaFormat_setInt32(config.get(), AMEDIAFORMAT_KEY_BIT_RATE, bitrate);
- AMediaFormat_setInt32(config.get(), AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, i_interval);
- AMediaFormat_setInt32(config.get(), AMEDIAFORMAT_KEY_COLOR_FORMAT, colorFormat);
-
- return config;
-}
-
-static int32_t getOptimalBitrate(int w, int h) {
- return (w * h <= 640 * 480) ? 1000000 :
- (w * h <= 1280 * 720) ? 2000000 :
- (w * h <= 1920 * 1080) ? 6000000 :
- 10000000;
-}
-
-//-----------------------------------------------------------------------------
-// Tests
-//-----------------------------------------------------------------------------
-static bool runNativeEncoderTest(
- JNIEnv *env, int fd, jlong offset, jlong fileSize,
- jstring jmime, int w, int h,
- const std::vector<DParamRef>& dynParams,
- int32_t numFrames,
- bool usePersistentSurface) {
-
- // If dynamic I-frame is requested, set large-enough i-period
- // so that auto I-frames do not interfere with the ones explicitly requested,
- // and hence simplify validation.
- bool hasDynamicSyncRequest = false;
-
- // If dynamic bitrate updates are requested, set bitrate mode to CBR to
- // ensure bitrate within 'window of two updates' remains constant
- bool hasDynamicBitrateChanges = false;
-
- for (const DParamRef &d : dynParams) {
- int32_t temp;
- if (AMediaFormat_getInt32(d->param(), TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME, &temp)) {
- hasDynamicSyncRequest = true;
- } else if (AMediaFormat_getInt32(d->param(), TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE, &temp)) {
- hasDynamicBitrateChanges = true;
- }
- }
-
- const char* cmime = env->GetStringUTFChars(jmime, nullptr);
- std::string mime = cmime;
- env->ReleaseStringUTFChars(jmime, cmime);
-
- float fps = 30.0f;
- std::shared_ptr<AMediaFormat> config = createMediaFormat(
- mime, w, h, kColorFormatSurface,
- getOptimalBitrate(w, h),
- fps,
- hasDynamicSyncRequest ? numFrames / fps : 1 /*sec*/);
-
- if (hasDynamicBitrateChanges) {
- AMediaFormat_setInt32(config.get(), TBD_AMEDIAFORMAT_KEY_BIT_RATE_MODE, kBitrateModeConstant);
- }
-
- std::shared_ptr<Source> src = createDecoderSource(
- w, h, kColorFormatSurface, fps,
- true /*looping*/,
- hasDynamicSyncRequest | hasDynamicBitrateChanges, /*regulate feeding rate*/
- fd, offset, fileSize);
-
- std::unique_ptr<RunConfig> runConfig = std::make_unique<RunConfig>(numFrames, config);
- for (const DParamRef &d : dynParams) {
- runConfig->add(d);
- }
-
- std::string debugOutputFileName = "";
- std::shared_ptr<NativeEncoder> enc(new NativeEncoder(debugOutputFileName));
-
- if (usePersistentSurface) {
- std::shared_ptr<ANativeWindow> persistentSurface = enc->getPersistentSurface();
- enc->prepare(std::move(runConfig), persistentSurface);
- src->prepare(nullptr /*bufferListener*/, persistentSurface);
- } else {
- enc->prepare(std::move(runConfig));
- src->prepare(nullptr /*bufferListener*/, enc->getSurface());
- }
-
- src->start();
- enc->start();
-
- enc->waitForCompletion();
-
- Status status = enc->validate();
-
- src->stop();
- enc->reset();
-
- return status == OK;
-}
-
-extern "C" jboolean Java_android_media_cts_NativeEncoderTest_testEncodeSurfaceNative(
- JNIEnv *env, jclass /*clazz*/, int fd, jlong offset, jlong fileSize,
- jstring jmime, int w, int h) {
-
- std::vector<DParamRef> dynParams;
- return runNativeEncoderTest(env, fd, offset, fileSize, jmime, w, h,
- dynParams, 300, false /*usePersistentSurface*/);
-
-}
-
-extern "C" jboolean Java_android_media_cts_NativeEncoderTest_testEncodePersistentSurfaceNative(
- JNIEnv *env, jclass /*clazz*/, int fd, jlong offset, jlong fileSize,
- jstring jmime, int w, int h) {
-
- std::vector<DParamRef> dynParams;
- return runNativeEncoderTest(env, fd, offset, fileSize, jmime, w, h,
- dynParams, 300, true /*usePersistentSurface*/);
-}
-
-extern "C" jboolean Java_android_media_cts_NativeEncoderTest_testEncodeSurfaceDynamicSyncFrameNative(
- JNIEnv *env, jclass /*clazz*/, int fd, jlong offset, jlong fileSize,
- jstring jmime, int w, int h) {
-
- std::vector<DParamRef> dynParams;
- for (int32_t frameNum : {40, 75, 160, 180, 250}) {
- dynParams.push_back(DynamicParam::newRequestSync(frameNum));
- }
-
- return runNativeEncoderTest(env, fd, offset, fileSize, jmime, w, h,
- dynParams, 300, false /*usePersistentSurface*/);
-}
-
-extern "C" jboolean Java_android_media_cts_NativeEncoderTest_testEncodeSurfaceDynamicBitrateNative(
- JNIEnv *env, jclass /*clazz*/, int fd, jlong offset, jlong fileSize,
- jstring jmime, int w, int h) {
-
- int32_t bitrate = getOptimalBitrate(w, h);
- std::vector<DParamRef> dynParams;
-
- dynParams.push_back(DynamicParam::newBitRate(100, bitrate/2));
- dynParams.push_back(DynamicParam::newBitRate(200, 3*bitrate/4));
- dynParams.push_back(DynamicParam::newBitRate(300, bitrate));
-
- return runNativeEncoderTest(env, fd, offset, fileSize, jmime, w, h,
- dynParams, 400, false /*usePersistentSurface*/);
-}
-
diff --git a/tests/tests/media/libmediandkjni/native_media_utils.cpp b/tests/tests/media/libmediandkjni/native_media_utils.cpp
index 7596cbb..21b7f7f 100644
--- a/tests/tests/media/libmediandkjni/native_media_utils.cpp
+++ b/tests/tests/media/libmediandkjni/native_media_utils.cpp
@@ -27,11 +27,6 @@
namespace Utils {
-const char * TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
-const char * TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE = "video-bitrate";
-
-const char * TBD_AMEDIAFORMAT_KEY_BIT_RATE_MODE = "bitrate-mode";
-
Status Thread::startThread() {
assert(mHandle == 0);
if (pthread_create(&mHandle, nullptr, Thread::thread_wrapper, this) != 0) {
@@ -56,273 +51,4 @@
return nullptr;
}
-int32_t RunConfig::dynamicParamsOfKind(
- const char *key, std::vector<DParamRef>& paramsList) const {
- paramsList.clear();
- for (const DParamRef& d : mParams) {
- assert(d->param() != nullptr);
-
- if (!strncmp(key, TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME,
- strlen(TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME))) {
- int32_t tmp;
- if (AMediaFormat_getInt32(d->param(), TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME, &tmp)) {
- paramsList.push_back(d);
- }
-
- } else if (!strncmp(key, TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE,
- strlen(TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE))) {
- int32_t tmp;
- if (AMediaFormat_getInt32(d->param(), TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE, &tmp)) {
- paramsList.push_back(d);
- }
- }
- }
- return (int32_t)paramsList.size();
-}
-
-static bool comparePTS(const AMediaCodecBufferInfo& l, const AMediaCodecBufferInfo& r) {
- return l.presentationTimeUs < r.presentationTimeUs;
-}
-
-int32_t Stats::getBitrateAverage(int32_t frameNumFrom, int32_t frameNumTo) const {
- int64_t sum = 0;
- assert(frameNumFrom >= 0 && frameNumTo < mInfos.size());
- for (int i = frameNumFrom; i < frameNumTo; ++i) {
- sum += mInfos[i].size;
- }
- sum *= 8; // kB -> kb
-
- auto from = mInfos.begin() + frameNumFrom;
- auto to = mInfos.begin() + frameNumTo;
- int64_t duration = (*std::max_element(from, to, comparePTS)).presentationTimeUs
- - (*std::min_element(from, to, comparePTS)).presentationTimeUs;
- if (duration <= 0) {
- return 0;
- }
-
- int64_t avg = (sum * 1e6) / duration;
- return (int32_t)avg;
-}
-
-int32_t Stats::getBitratePeak(
- int32_t frameNumFrom, int32_t frameNumTo, int32_t windowSize) const {
- int64_t sum = 0;
- int64_t maxSum = 0;
- assert(frameNumFrom >= 0 && frameNumTo < mInfos.size());
- assert(windowSize < (frameNumTo - frameNumFrom));
-
- for (int i = frameNumFrom; i < frameNumTo; ++i) {
- sum += mInfos[i].size;
- if (i >= windowSize) {
- sum -= mInfos[i - windowSize].size;
- }
- maxSum = sum > maxSum ? sum : maxSum;
- }
- maxSum *= 8; // kB -> kb
- int64_t duration = mInfos[frameNumTo].presentationTimeUs -
- mInfos[frameNumFrom].presentationTimeUs;
- if (duration <= 0) {
- return 0;
- }
-
- int64_t peak = (maxSum * 1e6) / duration;
- return (int32_t)peak;
-}
-
-int32_t Stats::getSyncFrameNext(int32_t frameNumWhence) const {
- assert(frameNumWhence >= 0 && frameNumWhence < mInfos.size());
- int i = frameNumWhence;
- for (; i < (int)mInfos.size(); ++i) {
- if (mInfos[i].flags & TBD_AMEDIACODEC_BUFFER_FLAG_KEY_FRAME) {
- return i;
- }
- }
- return -1;
-}
-
-Status Validator::checkOverallBitrate(const Stats &stats, const RunConfig& config) {
- // skip this check if bitrate was updated dynamically
- ALOGV("DEBUG: checkOverallBitrate");
- std::vector<DParamRef> tmp;
- if (config.dynamicParamsOfKind(TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE, tmp) > 0) {
- ALOGV("DEBUG: checkOverallBitrate: dynamic bitrate enabled");
- return OK;
- }
-
- int32_t bitrate = 0;
- if (!AMediaFormat_getInt32(config.format(), AMEDIAFORMAT_KEY_BIT_RATE, &bitrate)) {
- // should not happen
- ALOGV("DEBUG: checkOverallBitrate: bitrate was not configured !");
- return FAIL;
- }
- assert(bitrate > 0);
-
- int32_t avgBitrate = stats.getBitrateAverage(0, config.frameCount() - 1);
- float deviation = (avgBitrate - bitrate) * 100 / bitrate;
- ALOGI("RESULT: Bitrate expected=%d Achieved=%d Deviation=%.2g%%",
- bitrate, avgBitrate, deviation);
-
- if (fabs(deviation) > kBitrateDeviationPercentMax) {
- ALOGI("RESULT: ERROR: bitrate deviation(%.2g%%) exceeds threshold (+/-%.2g%%)",
- deviation, kBitrateDeviationPercentMax);
- return FAIL;
- }
-
- // TODO
- // if bitrate mode was set to CBR, check for peak-bitrate deviation (+/-20%?)
- return OK;
-}
-
-Status Validator::checkFramerate(const Stats&, const RunConfig&) {
- // TODO - tricky if frames are reordered
- return OK;
-}
-
-Status Validator::checkIntraPeriod(const Stats& stats, const RunConfig& config) {
- float framerate;
- if (!AMediaFormat_getFloat(config.format(), AMEDIAFORMAT_KEY_FRAME_RATE, &framerate)) {
- // should not happen
- ALOGV("DEBUG: checkIntraPeriod: framerate was not configured ! : %s",
- AMediaFormat_toString(config.format()));
- return OK;
- }
-
- int32_t intraPeriod;
- if (!AMediaFormat_getInt32(config.format(), AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, &intraPeriod)) {
- // should not happen
- ALOGV("DEBUG: checkIntraPeriod: I-period was not configured !");
- return OK;
- }
-
- // TODO: handle special cases
- // intraPeriod = 0 => all I
- // intraPeriod < 0 => infinite GOP
- if (intraPeriod <= 0) {
- return OK;
- }
-
- int32_t iInterval = framerate * intraPeriod;
-
- if (iInterval >= stats.frameCount()) {
- ALOGV("RESULT: Intra-period %d exceeds frame-count %d ..skipping",
- iInterval, stats.frameCount());
- return OK;
- }
-
- int32_t numGopFound = 0;
- int32_t sumGopDistance = 0;
- int32_t lastKeyLocation = stats.getSyncFrameNext(0);
- for (;;) {
- int32_t nextKeyLocation = stats.getSyncFrameNext(lastKeyLocation + iInterval - kSyncFrameDeviationFramesMax);
- if (nextKeyLocation < 0) {
- break;
- }
- if (abs(nextKeyLocation - lastKeyLocation - iInterval) > kSyncFrameDeviationFramesMax) {
- ALOGE("RESULT: ERROR: Intra period at frame %d is %d (expected %d +/-%d)",
- lastKeyLocation, nextKeyLocation - lastKeyLocation, iInterval,
- kSyncFrameDeviationFramesMax);
- return FAIL;
- }
- ++numGopFound;
- sumGopDistance += (nextKeyLocation - lastKeyLocation);
- lastKeyLocation = nextKeyLocation;
- }
-
- if (numGopFound) {
- ALOGI("RESULT: Intra-period: configured=%d frames (%d sec). Actual=%d frames",
- iInterval, intraPeriod, sumGopDistance / numGopFound);
- }
-
- return OK;
-}
-
-Status Validator::checkDynamicKeyFrames(const Stats& stats, const RunConfig& config) {
- ALOGV("DEBUG: checkDynamicKeyFrames");
- std::vector<DParamRef> keyRequests;
- if (config.dynamicParamsOfKind(TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME, keyRequests) <= 0) {
- ALOGV("DEBUG: dynamic key-frames were not requested");
- return OK;
- }
-
- std::string debugStr = "";
- bool fail = false;
- for (DParamRef &d : keyRequests) {
- int32_t generatedKeyLocation = stats.getSyncFrameNext(d->frameNum());
- if (generatedKeyLocation - d->frameNum() > kSyncFrameDeviationFramesMax) {
- ALOGI("RESULT: ERROR: Dynamic sync-frame requested at frame=%d, got at frame=%d",
- d->frameNum(), generatedKeyLocation);
- fail = true;
- }
- char tmp[128];
- snprintf(tmp, 128, " %d/%d,", generatedKeyLocation, d->frameNum());
- debugStr = debugStr + std::string(tmp);
- }
- ALOGI("RESULT: Dynamic Key-frame locations - actual/requested :");
- ALOGI("RESULT: %s", debugStr.c_str());
-
- return fail ? FAIL : OK;
-}
-
-Status Validator::checkDynamicBitrate(const Stats& stats, const RunConfig& config) {
- // Checking bitrate convergence between two updates makes sense if requested along with CBR
- // check if CBR mode has been set. If not, simply pass
- int32_t bitrateMode;
- if (!AMediaFormat_getInt32(config.format(), TBD_AMEDIAFORMAT_KEY_BIT_RATE_MODE,
- &bitrateMode) || bitrateMode != kBitrateModeConstant) {
- ALOGV("DEBUG: checkDynamicBitrate: skipping since CBR not requested");
- return OK; //skip
- }
-
- // check if dynamic bitrates were requested
- std::vector<DParamRef> bitrateUpdates;
- if (config.dynamicParamsOfKind(TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE, bitrateUpdates) <= 0) {
- ALOGV("DEBUG: checkDynamicBitrate: dynamic bitrates not requested !");
- return OK; //skip
- }
- int32_t bitrate = 0;
- if (!AMediaFormat_getInt32(config.format(), AMEDIAFORMAT_KEY_BIT_RATE, &bitrate)) {
- // should not happen
- ALOGV("DEBUG: checkDynamicBitrate: bitrate was not configured !");
- return OK; //skip
- }
- assert(bitrate > 0);
-
- std::string debugStr = "";
- int32_t lastBitrateUpdateFrameNum = 0;
- int32_t lastBitrate = bitrate;
- bool fail = false;
-
- for (DParamRef &d : bitrateUpdates) {
- int32_t updatedBitrate = 0;
- if (!AMediaFormat_getInt32(
- d->param(), TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE, &updatedBitrate)) {
- ALOGE("BUG: expected dynamic bitrate");
- continue;
- }
- assert(updatedBitrate > 0);
-
- int32_t lastAverage = stats.getBitrateAverage(lastBitrateUpdateFrameNum, d->frameNum() - 1);
- float deviation = (lastAverage - lastBitrate) * 100 / lastBitrate;
-
- if (fabs(deviation) > kBitrateDeviationPercentMax) {
- ALOGI("RESULT: ERROR: dynamic bitrate deviation(%.2g%%) exceeds threshold (+/-%.2g%%)",
- deviation, kBitrateDeviationPercentMax);
- fail |= true;
- }
-
- char tmp[128];
- snprintf(tmp, 128, " [%d - %d] %d/%d,",
- lastBitrateUpdateFrameNum, d->frameNum() - 1, lastAverage, lastBitrate);
- debugStr = debugStr + std::string(tmp);
- lastBitrate = updatedBitrate;
- lastBitrateUpdateFrameNum = d->frameNum();
- }
-
- ALOGI("RESULT: Dynamic Bitrates : [from-frame - to-frame] actual/expected :");
- ALOGI("RESULT: %s", debugStr.c_str());
-
- return fail ? FAIL : OK;
-}
-
-
}; // namespace Utils
diff --git a/tests/tests/media/libmediandkjni/native_media_utils.h b/tests/tests/media/libmediandkjni/native_media_utils.h
index 8a1751e..e5842f7 100644
--- a/tests/tests/media/libmediandkjni/native_media_utils.h
+++ b/tests/tests/media/libmediandkjni/native_media_utils.h
@@ -32,20 +32,6 @@
namespace Utils {
-// constants not defined in NDK api
-extern const char * TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME;
-extern const char * TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE;
-static const uint32_t TBD_AMEDIACODEC_BUFFER_FLAG_KEY_FRAME = 0x1;
-
-extern const char * TBD_AMEDIAFORMAT_KEY_BIT_RATE_MODE;
-static const int32_t kBitrateModeConstant = 2;
-static const int32_t kColorFormatSurface = 0x7f000789;
-
-// tolerances
-// Keep in sync with the variation at src/android/media/cts/VideoCodecTest.java
-static const float kBitrateDeviationPercentMax = 20.0;
-static const int32_t kSyncFrameDeviationFramesMax = 5;
-
enum Status : int32_t {
FAIL = -1,
OK = 0,
@@ -92,117 +78,6 @@
ANativeWindow_release(_a);
}
-/*
- * Dynamic paramater that will be applied via AMediaCodec_setParamater(..)
- * during the encoding process, at the given frame number
- */
-struct DynamicParam {
- DynamicParam() = delete;
- DynamicParam(const DynamicParam&) = delete;
- ~DynamicParam() = default;
-
- static std::shared_ptr<DynamicParam> newBitRate(int atFrame, int32_t bitrate) {
- DynamicParam *d = new DynamicParam(atFrame);
- AMediaFormat_setInt32(d->param(), TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE, bitrate);
- return std::shared_ptr<DynamicParam>(d);
- }
- static std::shared_ptr<DynamicParam> newRequestSync(int atFrame) {
- DynamicParam *d = new DynamicParam(atFrame);
- AMediaFormat_setInt32(d->param(), TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME, 0 /*ignore*/);
- return std::shared_ptr<DynamicParam>(d);
- }
-
- inline int frameNum() const {
- return mFrameNum;
- }
- inline AMediaFormat *param() const {
- return mParam.get();
- }
-
-private:
- DynamicParam(int _at)
- : mFrameNum(_at) {
- mParam = std::shared_ptr<AMediaFormat>(AMediaFormat_new(), deleter_AMediaFormat);
- }
-
- int mFrameNum;
- std::shared_ptr<AMediaFormat> mParam;
-};
-
-using DParamRef = std::shared_ptr<DynamicParam>;
-
-/*
- * Configuration to the encoder (static + dynamic)
- */
-struct RunConfig {
- RunConfig(const RunConfig&) = delete;
- RunConfig(int32_t numFramesToEncode, std::shared_ptr<AMediaFormat> staticParams)
- : mNumFramesToEncode (numFramesToEncode),
- mStaticParams(staticParams) {
- }
- void add(const DParamRef& p) {
- mParams.push_back(p);
- }
-
- AMediaFormat* format() const {
- return mStaticParams.get();
- }
- const std::vector<DParamRef>& dynamicParams() const {
- return mParams;
- }
- int32_t frameCount() const {
- return mNumFramesToEncode;
- }
- int32_t dynamicParamsOfKind(
- const char *key, std::vector<DParamRef>& ) const;
-
-private:
- int32_t mNumFramesToEncode;
- std::vector<DParamRef> mParams;
- std::shared_ptr<AMediaFormat> mStaticParams;
-};
-
-/*
- * Encoded output statistics
- * provides helpers to compute windowed average of bitrate and search for I-frames
- */
-struct Stats {
- Stats() = default;
- Stats(const Stats&) = delete;
- void add(const AMediaCodecBufferInfo &info) {
- mInfos.push_back(info);
- }
- void setOutputFormat(std::shared_ptr<AMediaFormat> fmt) {
- mOutputFormat = fmt;
- }
- int32_t frameCount() const {
- return (int32_t)mInfos.size();
- }
- const std::vector<AMediaCodecBufferInfo>& infos() const {
- return mInfos;
- }
-
- int32_t getBitrateAverage(int32_t frameNumFrom, int32_t frameNumTo) const;
- int32_t getBitratePeak(int32_t frameNumFrom, int32_t frameNumTo, int32_t windowSize) const;
- int32_t getSyncFrameNext(int32_t frameNumWhence) const;
-
-private:
- std::vector<AMediaCodecBufferInfo> mInfos;
- std::shared_ptr<AMediaFormat> mOutputFormat;
-};
-
-/*
- * Helpers to validate output (Stats) based on expected settings (RunConfig)
- * Check for validity of both static and dynamic settings
- */
-struct Validator {
- static Status checkOverallBitrate(const Stats&, const RunConfig&);
- static Status checkFramerate(const Stats&, const RunConfig&);
- static Status checkIntraPeriod(const Stats&, const RunConfig&);
- static Status checkDynamicKeyFrames(const Stats&, const RunConfig&);
- static Status checkDynamicBitrate(const Stats&, const RunConfig&);
-};
-
}; //namespace Utils
#endif // _NATIVE_MEDIA_UTILS_H_
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index d17e702..7e75fb7 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -35,7 +35,6 @@
import static android.media.MediaFormat.MIMETYPE_VIDEO_VP9;
import android.media.MediaPlayer;
import android.os.Build;
-import android.os.SystemProperties;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Range;
@@ -697,6 +696,7 @@
private int getActualMax(
boolean isEncoder, String name, String mime, CodecCapabilities caps, int max) {
int flag = isEncoder ? MediaCodec.CONFIGURE_FLAG_ENCODE : 0;
+ boolean memory_limited = false;
MediaFormat format = createMinFormat(mime, caps);
Log.d(TAG, "Test format " + format);
Vector<MediaCodec> codecs = new Vector<MediaCodec>();
@@ -716,6 +716,7 @@
am.getMemoryInfo(outInfo);
if (outInfo.lowMemory) {
Log.d(TAG, "System is in low memory condition, stopping. max: " + i);
+ memory_limited = true;
break;
}
} catch (IllegalArgumentException e) {
@@ -745,6 +746,10 @@
codecs.get(i).release();
}
codecs.clear();
+ // encode both actual max and whether we ran out of memory
+ if (memory_limited) {
+ actualMax = -actualMax;
+ }
return actualMax;
}
@@ -773,13 +778,20 @@
}
public void testGetMaxSupportedInstances() {
- final int MAX_INSTANCES = 32;
StringBuilder xmlOverrides = new StringBuilder();
MediaCodecList allCodecs = new MediaCodecList(MediaCodecList.ALL_CODECS);
+ final boolean isLowRam = ActivityManager.isLowRamDeviceStatic();
for (MediaCodecInfo info : allCodecs.getCodecInfos()) {
Log.d(TAG, "codec: " + info.getName());
Log.d(TAG, " isEncoder = " + info.isEncoder());
+ // don't bother testing aliases
+ if (info.isAlias()) {
+ Log.d(TAG, "skipping: " + info.getName() + " is an alias for " +
+ info.getCanonicalName());
+ continue;
+ }
+
String[] types = info.getSupportedTypes();
for (int j = 0; j < types.length; ++j) {
if (!knownTypes(types[j])) {
@@ -788,14 +800,55 @@
}
Log.d(TAG, "calling getCapabilitiesForType " + types[j]);
CodecCapabilities caps = info.getCapabilitiesForType(types[j]);
- int max = caps.getMaxSupportedInstances();
- Log.d(TAG, "getMaxSupportedInstances returns " + max);
- assertTrue(max > 0);
+ int advertised = caps.getMaxSupportedInstances();
+ Log.d(TAG, "getMaxSupportedInstances returns " + advertised);
+ assertTrue(advertised > 0);
+ // see how well the declared max matches against reality
+
+ int tryMax = isLowRam ? 16 : 32;
+ int tryMin = isLowRam ? 4 : 16;
+
+ int trials = Math.min(advertised + 2, tryMax);
int actualMax = getActualMax(
- info.isEncoder(), info.getName(), types[j], caps, MAX_INSTANCES);
- Log.d(TAG, "actualMax " + actualMax + " vs reported max " + max);
- if (actualMax < (int)(max * 0.9) || actualMax > (int) Math.ceil(max * 1.1)) {
+ info.isEncoder(), info.getName(), types[j], caps, trials);
+ Log.d(TAG, "actualMax " + actualMax + " vs advertised " + advertised
+ + " tryMin " + tryMin + " tryMax " + tryMax);
+
+ boolean memory_limited = false;
+ if (actualMax < 0) {
+ memory_limited = true;
+ actualMax = -actualMax;
+ }
+
+ boolean compliant = true;
+ if (info.isHardwareAccelerated()) {
+ // very specific bounds for HW codecs
+ // so the adv+2 above is to see if the HW codec lets us go beyond adv
+ // (it should not)
+ if (actualMax != Math.min(advertised, tryMax)) {
+ Log.d(TAG, "NO: hwcodec " + actualMax + " != min(" + advertised +
+ "," + tryMax + ")");
+ compliant = false;
+ }
+ } else {
+ // sw codecs get a little more relaxation due to memory pressure
+ if (actualMax >= Math.min(advertised, tryMax)) {
+ // no memory issues, and we allocated them all
+ Log.d(TAG, "OK: swcodec " + actualMax + " >= min(" + advertised +
+ "," + tryMax + ")");
+ } else if (actualMax >= Math.min(advertised, tryMin) &&
+ memory_limited) {
+ // memory issues, but we hit our floors
+ Log.d(TAG, "OK: swcodec " + actualMax + " >= min(" + advertised +
+ "," + tryMin + ") + memory limited");
+ } else {
+ Log.d(TAG, "NO: swcodec didn't meet criteria");
+ compliant = false;
+ }
+ }
+
+ if (!compliant) {
String codec = "<MediaCodec name=\"" + info.getName() +
"\" type=\"" + types[j] + "\" >";
String limit = " <Limit name=\"concurrent-instances\" max=\"" +
diff --git a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java b/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
index 238da0b..3f6e690 100644
--- a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
+++ b/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
@@ -17,6 +17,7 @@
package android.media.cts;
import static android.content.Context.AUDIO_SERVICE;
+import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
import static android.media.cts.StubMediaRoute2ProviderService.FEATURES_SPECIAL;
import static android.media.cts.StubMediaRoute2ProviderService.FEATURE_SAMPLE;
@@ -90,6 +91,9 @@
private static final String TEST_VALUE = "test_value";
private static final RouteDiscoveryPreference EMPTY_DISCOVERY_PREFERENCE =
new RouteDiscoveryPreference.Builder(Collections.emptyList(), false).build();
+ private static final RouteDiscoveryPreference LIVE_AUDIO_DISCOVERY_PREFERENCE =
+ new RouteDiscoveryPreference.Builder(
+ Collections.singletonList(FEATURE_LIVE_AUDIO), false).build();
@Before
public void setUp() throws Exception {
@@ -124,10 +128,16 @@
@Test
public void testGetRoutesAfterCreation() {
- List<MediaRoute2Info> initialRoutes = mRouter2.getRoutes();
- assertFalse(initialRoutes.isEmpty());
- for (MediaRoute2Info route : initialRoutes) {
- assertTrue(route.isSystemRoute());
+ RouteCallback routeCallback = new RouteCallback() {};
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, LIVE_AUDIO_DISCOVERY_PREFERENCE);
+ try {
+ List<MediaRoute2Info> initialRoutes = mRouter2.getRoutes();
+ assertFalse(initialRoutes.isEmpty());
+ for (MediaRoute2Info route : initialRoutes) {
+ assertTrue(route.getFeatures().contains(FEATURE_LIVE_AUDIO));
+ }
+ } finally {
+ mRouter2.unregisterRouteCallback(routeCallback);
}
}
@@ -138,18 +148,13 @@
public void testGetRoutes() throws Exception {
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(FEATURES_SPECIAL);
- int systemRouteCount = 0;
int remoteRouteCount = 0;
for (MediaRoute2Info route : routes.values()) {
- if (route.isSystemRoute()) {
- systemRouteCount++;
- } else {
+ if (!route.isSystemRoute()) {
remoteRouteCount++;
}
}
- // Can be greater than 1 if BT devices are connected.
- assertTrue(systemRouteCount > 0);
assertEquals(1, remoteRouteCount);
assertNotNull(routes.get(ROUTE_ID_SPECIAL_FEATURE));
}
@@ -996,8 +1001,7 @@
}
};
- mRouter2.registerRouteCallback(mExecutor, routeCallback,
- new RouteDiscoveryPreference.Builder(new ArrayList<>(), true).build());
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, LIVE_AUDIO_DISCOVERY_PREFERENCE);
try {
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, targetVolume, 0);
diff --git a/tests/tests/media/src/android/media/cts/NativeEncoderTest.java b/tests/tests/media/src/android/media/cts/NativeEncoderTest.java
deleted file mode 100644
index 5cacfe1..0000000
--- a/tests/tests/media/src/android/media/cts/NativeEncoderTest.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.cts;
-
-import android.media.cts.R;
-
-import android.content.res.AssetFileDescriptor;
-import android.content.res.Resources;
-import android.net.Uri;
-import android.os.Environment;
-import android.os.ParcelFileDescriptor;
-import android.platform.test.annotations.AppModeFull;
-import android.util.Log;
-import android.view.Surface;
-import android.webkit.cts.CtsTestServer;
-
-import com.android.compatibility.common.util.MediaUtils;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-@AppModeFull(reason = "TODO: evaluate and port to instant")
-public class NativeEncoderTest extends MediaPlayerTestBase {
- private static final String TAG = "NativeEncoderTest";
- private static Resources mResources;
-
- private static final String MIME_AVC = "video/avc";
- private static final String MIME_HEVC = "video/hevc";
- private static final String MIME_VP8 = "video/x-vnd.on2.vp8";
-
- private static int mResourceVideo720p;
- private static int mResourceVideo360p;
-
- static {
- System.loadLibrary("ctsmediacodec_jni");
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mResources = mContext.getResources();
-
- mResourceVideo720p =
- R.raw.bbb_s4_1280x720_webm_vp8_8mbps_30fps_opus_mono_64kbps_48000hz;
- mResourceVideo360p =
- R.raw.bbb_s1_640x360_webm_vp8_2mbps_30fps_vorbis_5ch_320kbps_48000hz;
- }
-
-
- private boolean testEncode(int res, String mime, int width, int height) {
- AssetFileDescriptor fd = mResources.openRawResourceFd(res);
-
- return testEncodeSurfaceNative(
- fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength(),
- mime, width, height);
- }
- private static native boolean testEncodeSurfaceNative(int fd, long offset, long size,
- String mime, int width, int height);
-
- public void testEncodeSurfaceH264720p() throws Exception {
- boolean status = testEncode(mResourceVideo720p, MIME_AVC, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodeSurfaceVp8720p() throws Exception {
- boolean status = testEncode(mResourceVideo720p, MIME_VP8, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodeSurfaceHevc720p() throws Exception {
- boolean status = testEncode(mResourceVideo720p, MIME_HEVC, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodeSurfaceH264360p() throws Exception {
- boolean status = testEncode(mResourceVideo360p, MIME_AVC, 640, 360);
- assertTrue("native encode error", status);
- }
- public void testEncodeSurfaceVp8360p() throws Exception {
- boolean status = testEncode(mResourceVideo360p, MIME_VP8, 640, 360);
- assertTrue("native encode error", status);
- }
- public void testEncodeSurfaceHevc360p() throws Exception {
- boolean status = testEncode(mResourceVideo360p, MIME_HEVC, 640, 360);
- assertTrue("native encode error", status);
- }
-
-
- private boolean testEncodeDynamicSyncFrame(int res, String mime, int width, int height) {
- AssetFileDescriptor fd = mResources.openRawResourceFd(res);
-
- return testEncodeSurfaceDynamicSyncFrameNative(
- fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength(),
- mime, width, height);
- }
- private static native boolean testEncodeSurfaceDynamicSyncFrameNative(int fd, long offset, long size,
- String mime, int width, int height);
-
- public void testEncodeDynamicSyncFrameH264720p() throws Exception {
- boolean status = testEncodeDynamicSyncFrame(mResourceVideo720p, MIME_AVC, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicSyncFrameVp8720p() throws Exception {
- boolean status = testEncodeDynamicSyncFrame(mResourceVideo720p, MIME_VP8, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicSyncFrameHevc720p() throws Exception {
- boolean status = testEncodeDynamicSyncFrame(mResourceVideo720p, MIME_HEVC, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicSyncFrameH264360p() throws Exception {
- boolean status = testEncodeDynamicSyncFrame(mResourceVideo360p, MIME_AVC, 640, 360);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicSyncFrameVp8360p() throws Exception {
- boolean status = testEncodeDynamicSyncFrame(mResourceVideo360p, MIME_VP8, 640, 360);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicSyncFrameHevc360p() throws Exception {
- boolean status = testEncodeDynamicSyncFrame(mResourceVideo360p, MIME_HEVC, 640, 360);
- assertTrue("native encode error", status);
- }
-
-
- private boolean testEncodeDynamicBitrate(int res, String mime, int width, int height) {
- AssetFileDescriptor fd = mResources.openRawResourceFd(res);
-
- return testEncodeSurfaceDynamicBitrateNative(
- fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength(),
- mime, width, height);
- }
- private static native boolean testEncodeSurfaceDynamicBitrateNative(int fd, long offset, long size,
- String mime, int width, int height);
-
- public void testEncodeDynamicBitrateH264720p() throws Exception {
- boolean status = testEncodeDynamicBitrate(mResourceVideo720p, MIME_AVC, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicBitrateVp8720p() throws Exception {
- boolean status = testEncodeDynamicBitrate(mResourceVideo720p, MIME_VP8, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicBitrateHevc720p() throws Exception {
- boolean status = testEncodeDynamicBitrate(mResourceVideo720p, MIME_HEVC, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicBitrateH264360p() throws Exception {
- boolean status = testEncodeDynamicBitrate(mResourceVideo360p, MIME_AVC, 640, 360);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicBitrateVp8360p() throws Exception {
- boolean status = testEncodeDynamicBitrate(mResourceVideo360p, MIME_VP8, 640, 360);
- assertTrue("native encode error", status);
- }
- public void testEncodeDynamicBitrateHevc360p() throws Exception {
- boolean status = testEncodeDynamicBitrate(mResourceVideo360p, MIME_HEVC, 640, 360);
- assertTrue("native encode error", status);
- }
-
-
- private boolean testEncodePersistentSurface(int res, String mime, int width, int height) {
- AssetFileDescriptor fd = mResources.openRawResourceFd(res);
-
- return testEncodePersistentSurfaceNative(
- fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength(),
- mime, width, height);
- }
-
- private static native boolean testEncodePersistentSurfaceNative(int fd, long offset, long size,
- String mime, int width, int height);
-
- public void testEncodePersistentSurface720p() throws Exception {
- boolean status = testEncodePersistentSurface(mResourceVideo720p, MIME_AVC, 1280, 720);
- assertTrue("native encode error", status);
- }
- public void testEncodePersistentSurface360p() throws Exception {
- boolean status = testEncodePersistentSurface(mResourceVideo360p, MIME_VP8, 640, 360);
- assertTrue("native encode error", status);
- }
-}
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp
index 79cd3f6..4d9194f 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp
@@ -274,8 +274,14 @@
AAudioStreamBuilder_setUsage(aaudioBuilder, systemUsage);
- // Get failed status when trying to create an AAudioStream using the Builder.
- ASSERT_EQ(AAUDIO_ERROR_ILLEGAL_ARGUMENT, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+ aaudio_result_t result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+
+ // Get failed status when trying to create an AAudioStream using the Builder. There are two
+ // potential failures: one if the device doesn't support the system usage, and the other
+ // if it does but this test doesn't have the MODIFY_AUDIO_ROUTING permission required to
+ // use it.
+ ASSERT_TRUE(result == AAUDIO_ERROR_ILLEGAL_ARGUMENT
+ || result == AAUDIO_ERROR_INTERNAL);
AAudioStreamBuilder_delete(aaudioBuilder);
}
}
diff --git a/tests/tests/net/Android.bp b/tests/tests/net/Android.bp
index 2b99a40..112799b 100644
--- a/tests/tests/net/Android.bp
+++ b/tests/tests/net/Android.bp
@@ -36,19 +36,20 @@
"src/**/*.java",
"src/**/*.kt",
],
-
+ jarjar_rules: "jarjar-rules-shared.txt",
static_libs: [
"FrameworksNetCommonTests",
"TestNetworkStackLib",
- "core-tests-support",
"compatibility-device-util-axt",
+ "core-tests-support",
"cts-net-utils",
"ctstestrunner-axt",
"ctstestserver",
- "mockwebserver",
"junit",
"junit-params",
"libnanohttpd",
+ "mockwebserver",
+ "net-utils-framework-common",
"truth-prebuilt",
],
diff --git a/tests/tests/net/jarjar-rules-shared.txt b/tests/tests/net/jarjar-rules-shared.txt
new file mode 100644
index 0000000..11dba74
--- /dev/null
+++ b/tests/tests/net/jarjar-rules-shared.txt
@@ -0,0 +1,2 @@
+# Module library in frameworks/libs/net
+rule com.android.net.module.util.** android.net.cts.util.@1
\ No newline at end of file
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java b/tests/tests/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
index d17d8e5..a19ba64 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
@@ -16,6 +16,7 @@
package android.net.cts;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
@@ -31,9 +32,11 @@
import static android.net.ConnectivityDiagnosticsManager.persistableBundleEquals;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
+import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static org.junit.Assert.assertEquals;
@@ -41,9 +44,15 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
@@ -55,13 +64,19 @@
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
import android.platform.test.annotations.AppModeFull;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.util.Pair;
import androidx.test.InstrumentationRegistry;
+import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.util.ArrayUtils;
import com.android.testutils.ArrayTrackRecord;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -71,7 +86,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
@RunWith(DevSdkIgnoreRunner.class)
@IgnoreUpTo(Build.VERSION_CODES.Q) // ConnectivityDiagnosticsManager did not exist in Q
@@ -85,6 +105,7 @@
private static final int FAIL_RATE_PERCENTAGE = 100;
private static final int UNKNOWN_DETECTION_METHOD = 4;
private static final int FILTERED_UNKNOWN_DETECTION_METHOD = 0;
+ private static final int CARRIER_CONFIG_CHANGED_BROADCAST_TIMEOUT = 5000;
private static final Executor INLINE_EXECUTOR = x -> x.run();
@@ -95,44 +116,71 @@
.removeCapability(NET_CAPABILITY_NOT_VPN)
.build();
- // Callback used to keep TestNetworks up when there are no other outstanding NetworkRequests
- // for it.
- private static final TestNetworkCallback TEST_NETWORK_CALLBACK = new TestNetworkCallback();
+ private static final String SHA_256 = "SHA-256";
+
+ private static final NetworkRequest CELLULAR_NETWORK_REQUEST =
+ new NetworkRequest.Builder().addTransportType(TRANSPORT_CELLULAR).build();
private static final IBinder BINDER = new Binder();
private Context mContext;
private ConnectivityManager mConnectivityManager;
private ConnectivityDiagnosticsManager mCdm;
+ private CarrierConfigManager mCarrierConfigManager;
+ private PackageManager mPackageManager;
+ private TelephonyManager mTelephonyManager;
+
+ // Callback used to keep TestNetworks up when there are no other outstanding NetworkRequests
+ // for it.
+ private TestNetworkCallback mTestNetworkCallback;
private Network mTestNetwork;
+ private ParcelFileDescriptor mTestNetworkFD;
+
+ private List<TestConnectivityDiagnosticsCallback> mRegisteredCallbacks;
@Before
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getContext();
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
mCdm = mContext.getSystemService(ConnectivityDiagnosticsManager.class);
+ mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+ mPackageManager = mContext.getPackageManager();
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
- mConnectivityManager.requestNetwork(TEST_NETWORK_REQUEST, TEST_NETWORK_CALLBACK);
+ mTestNetworkCallback = new TestNetworkCallback();
+ mConnectivityManager.requestNetwork(TEST_NETWORK_REQUEST, mTestNetworkCallback);
+
+ mRegisteredCallbacks = new ArrayList<>();
}
@After
public void tearDown() throws Exception {
- mConnectivityManager.unregisterNetworkCallback(TEST_NETWORK_CALLBACK);
-
+ mConnectivityManager.unregisterNetworkCallback(mTestNetworkCallback);
if (mTestNetwork != null) {
runWithShellPermissionIdentity(() -> {
final TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class);
tnm.teardownTestNetwork(mTestNetwork);
});
+ mTestNetwork = null;
+ }
+
+ if (mTestNetworkFD != null) {
+ mTestNetworkFD.close();
+ mTestNetworkFD = null;
+ }
+
+ for (TestConnectivityDiagnosticsCallback cb : mRegisteredCallbacks) {
+ mCdm.unregisterConnectivityDiagnosticsCallback(cb);
}
}
@Test
public void testRegisterConnectivityDiagnosticsCallback() throws Exception {
- mTestNetwork = setUpTestNetwork();
+ mTestNetworkFD = setUpTestNetwork().getFileDescriptor();
+ mTestNetwork = mTestNetworkCallback.waitForAvailable();
- final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback();
- mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb);
+ final TestConnectivityDiagnosticsCallback cb =
+ createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST);
final String interfaceName =
mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName();
@@ -142,9 +190,98 @@
}
@Test
+ public void testRegisterCallbackWithCarrierPrivileges() throws Exception {
+ assumeTrue(mPackageManager.hasSystemFeature(FEATURE_TELEPHONY));
+
+ final int subId = SubscriptionManager.getDefaultSubscriptionId();
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ fail("Need an active subscription. Please ensure that the device has working mobile"
+ + " data.");
+ }
+
+ final CarrierConfigReceiver carrierConfigReceiver = new CarrierConfigReceiver(subId);
+ mContext.registerReceiver(
+ carrierConfigReceiver,
+ new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+
+ final TestNetworkCallback testNetworkCallback = new TestNetworkCallback();
+
+ try {
+ doBroadcastCarrierConfigsAndVerifyOnConnectivityReportAvailable(
+ subId, carrierConfigReceiver, testNetworkCallback);
+ } finally {
+ runWithShellPermissionIdentity(
+ () -> mCarrierConfigManager.overrideConfig(subId, null),
+ android.Manifest.permission.MODIFY_PHONE_STATE);
+ mConnectivityManager.unregisterNetworkCallback(testNetworkCallback);
+ mContext.unregisterReceiver(carrierConfigReceiver);
+ }
+ }
+
+ private String getCertHashForThisPackage() throws Exception {
+ final PackageInfo pkgInfo =
+ mPackageManager.getPackageInfo(
+ mContext.getOpPackageName(), PackageManager.GET_SIGNATURES);
+ final MessageDigest md = MessageDigest.getInstance(SHA_256);
+ final byte[] certHash = md.digest(pkgInfo.signatures[0].toByteArray());
+ return IccUtils.bytesToHexString(certHash);
+ }
+
+ private void doBroadcastCarrierConfigsAndVerifyOnConnectivityReportAvailable(
+ int subId,
+ @NonNull CarrierConfigReceiver carrierConfigReceiver,
+ @NonNull TestNetworkCallback testNetworkCallback)
+ throws Exception {
+ final PersistableBundle carrierConfigs = new PersistableBundle();
+ carrierConfigs.putStringArray(
+ CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
+ new String[] {getCertHashForThisPackage()});
+
+ runWithShellPermissionIdentity(
+ () -> {
+ mCarrierConfigManager.overrideConfig(subId, carrierConfigs);
+ mCarrierConfigManager.notifyConfigChangedForSubId(subId);
+ },
+ android.Manifest.permission.MODIFY_PHONE_STATE);
+
+ // TODO(b/157779832): This should use android.permission.CHANGE_NETWORK_STATE. However, the
+ // shell does not have CHANGE_NETWORK_STATE, so use CONNECTIVITY_INTERNAL until the shell
+ // permissions are updated.
+ runWithShellPermissionIdentity(
+ () -> mConnectivityManager.requestNetwork(
+ CELLULAR_NETWORK_REQUEST, testNetworkCallback),
+ android.Manifest.permission.CONNECTIVITY_INTERNAL);
+
+ final Network network = testNetworkCallback.waitForAvailable();
+ assertNotNull(network);
+
+ assertTrue("Didn't receive broadcast for ACTION_CARRIER_CONFIG_CHANGED for subId=" + subId,
+ carrierConfigReceiver.waitForCarrierConfigChanged());
+ assertTrue("Don't have Carrier Privileges after adding cert for this package",
+ mTelephonyManager.createForSubscriptionId(subId).hasCarrierPrivileges());
+
+ // Wait for CarrierPrivilegesTracker to receive the ACTION_CARRIER_CONFIG_CHANGED
+ // broadcast. CPT then needs to update the corresponding DataConnection, which then
+ // updates ConnectivityService. Unfortunately, this update to the NetworkCapabilities in
+ // CS does not trigger NetworkCallback#onCapabilitiesChanged as changing the
+ // administratorUids is not a publicly visible change. In lieu of a better signal to
+ // detministically wait for, use Thread#sleep here.
+ Thread.sleep(500);
+
+ final TestConnectivityDiagnosticsCallback connDiagsCallback =
+ createAndRegisterConnectivityDiagnosticsCallback(CELLULAR_NETWORK_REQUEST);
+
+ final String interfaceName =
+ mConnectivityManager.getLinkProperties(network).getInterfaceName();
+ connDiagsCallback.expectOnConnectivityReportAvailable(
+ network, interfaceName, TRANSPORT_CELLULAR);
+ connDiagsCallback.assertNoCallback();
+ }
+
+ @Test
public void testRegisterDuplicateConnectivityDiagnosticsCallback() {
- final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback();
- mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb);
+ final TestConnectivityDiagnosticsCallback cb =
+ createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST);
try {
mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb);
@@ -168,10 +305,11 @@
@Test
public void testOnConnectivityReportAvailable() throws Exception {
- mTestNetwork = setUpTestNetwork();
+ final TestConnectivityDiagnosticsCallback cb =
+ createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST);
- final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback();
- mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb);
+ mTestNetworkFD = setUpTestNetwork().getFileDescriptor();
+ mTestNetwork = mTestNetworkCallback.waitForAvailable();
final String interfaceName =
mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName();
@@ -219,10 +357,11 @@
long timestampMillis,
@NonNull PersistableBundle extras)
throws Exception {
- mTestNetwork = setUpTestNetwork();
+ mTestNetworkFD = setUpTestNetwork().getFileDescriptor();
+ mTestNetwork = mTestNetworkCallback.waitForAvailable();
- final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback();
- mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb);
+ final TestConnectivityDiagnosticsCallback cb =
+ createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST);
final String interfaceName =
mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName();
@@ -250,10 +389,11 @@
}
private void verifyOnNetworkConnectivityReported(boolean hasConnectivity) throws Exception {
- mTestNetwork = setUpTestNetwork();
+ mTestNetworkFD = setUpTestNetwork().getFileDescriptor();
+ mTestNetwork = mTestNetworkCallback.waitForAvailable();
- final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback();
- mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb);
+ final TestConnectivityDiagnosticsCallback cb =
+ createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST);
// onConnectivityReportAvailable always invoked when the test network is established
final String interfaceName =
@@ -274,17 +414,12 @@
cb.assertNoCallback();
}
- @NonNull
- private Network waitForConnectivityServiceIdleAndGetNetwork() throws InterruptedException {
- // Get a new Network. This requires going through the ConnectivityService thread. Once it
- // completes, all previously enqueued messages on the ConnectivityService main Handler have
- // completed.
- final TestNetworkCallback callback = new TestNetworkCallback();
- mConnectivityManager.requestNetwork(TEST_NETWORK_REQUEST, callback);
- final Network network = callback.waitForAvailable();
- mConnectivityManager.unregisterNetworkCallback(callback);
- assertNotNull(network);
- return network;
+ private TestConnectivityDiagnosticsCallback createAndRegisterConnectivityDiagnosticsCallback(
+ NetworkRequest request) {
+ final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback();
+ mCdm.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, cb);
+ mRegisteredCallbacks.add(cb);
+ return cb;
}
/**
@@ -292,16 +427,16 @@
* to the Network being validated.
*/
@NonNull
- private Network setUpTestNetwork() throws Exception {
+ private TestNetworkInterface setUpTestNetwork() throws Exception {
final int[] administratorUids = new int[] {Process.myUid()};
- runWithShellPermissionIdentity(
+ return callWithShellPermissionIdentity(
() -> {
final TestNetworkManager tnm =
mContext.getSystemService(TestNetworkManager.class);
final TestNetworkInterface tni = tnm.createTunInterface(new LinkAddress[0]);
tnm.setupTestNetwork(tni.getInterfaceName(), administratorUids, BINDER);
+ return tni;
});
- return waitForConnectivityServiceIdleAndGetNetwork();
}
private static class TestConnectivityDiagnosticsCallback
@@ -326,13 +461,18 @@
public void expectOnConnectivityReportAvailable(
@NonNull Network network, @NonNull String interfaceName) {
+ expectOnConnectivityReportAvailable(network, interfaceName, TRANSPORT_TEST);
+ }
+
+ public void expectOnConnectivityReportAvailable(
+ @NonNull Network network, @NonNull String interfaceName, int transportType) {
final ConnectivityReport result =
(ConnectivityReport) mHistory.poll(CALLBACK_TIMEOUT_MILLIS, x -> true);
assertEquals(network, result.getNetwork());
final NetworkCapabilities nc = result.getNetworkCapabilities();
assertNotNull(nc);
- assertTrue(nc.hasTransport(TRANSPORT_TEST));
+ assertTrue(nc.hasTransport(transportType));
assertNotNull(result.getLinkProperties());
assertEquals(interfaceName, result.getLinkProperties().getInterfaceName());
@@ -386,4 +526,43 @@
mHistory.poll(NO_CALLBACK_INVOKED_TIMEOUT, x -> true));
}
}
+
+ private class CarrierConfigReceiver extends BroadcastReceiver {
+ private final CountDownLatch mLatch = new CountDownLatch(1);
+ private final int mSubId;
+
+ CarrierConfigReceiver(int subId) {
+ mSubId = subId;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
+ return;
+ }
+
+ final int subId =
+ intent.getIntExtra(
+ CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ if (mSubId != subId) return;
+
+ final PersistableBundle carrierConfigs = mCarrierConfigManager.getConfigForSubId(subId);
+ if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfigs)) return;
+
+ final String[] certs =
+ carrierConfigs.getStringArray(
+ CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY);
+ try {
+ if (ArrayUtils.contains(certs, getCertHashForThisPackage())) {
+ mLatch.countDown();
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ boolean waitForCarrierConfigChanged() throws Exception {
+ return mLatch.await(CARRIER_CONFIG_CHANGED_BROADCAST_TIMEOUT, TimeUnit.MILLISECONDS);
+ }
+ }
}
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index 2c74ac8..835f541 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -291,6 +291,7 @@
.setData(Uri.fromParts("package", packageName, null))
.addFlags(FLAG_ACTIVITY_NEW_TASK))
+ waitForIdle()
click("Permissions")
}
diff --git a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/IntentTest.kt b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/IntentTest.kt
index 9a24968..33a8966 100644
--- a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/IntentTest.kt
+++ b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/IntentTest.kt
@@ -24,9 +24,6 @@
import androidx.test.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
-import com.android.compatibility.common.util.SystemUtil.runShellCommand
-import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
-
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Test
@@ -42,12 +39,6 @@
class IntentTest : PackageInstallerTestBase() {
private val context = InstrumentationRegistry.getTargetContext()
- private fun setSecureFrp(secureFrp: Boolean) {
- runWithShellPermissionIdentity {
- runShellCommand("settings put secure secure_frp_mode ${if (secureFrp) 1 else 0}")
- }
- }
-
@After
fun disableSecureFrp() {
setSecureFrp(false)
diff --git a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt
index ad7c7fd..45eb038 100644
--- a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt
+++ b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt
@@ -198,6 +198,11 @@
uiDevice.executeShellCommand("settings put secure $secureSetting $value")
}
+ fun setSecureFrp(secureFrp: Boolean) {
+ uiDevice.executeShellCommand("settings --user 0 " +
+ "put secure secure_frp_mode ${if (secureFrp) 1 else 0}")
+ }
+
@After
fun unregisterInstallResultReceiver() {
try {
diff --git a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/SessionTest.kt b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/SessionTest.kt
index 24a1128..69096f8 100644
--- a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/SessionTest.kt
+++ b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/SessionTest.kt
@@ -98,7 +98,7 @@
@Test
fun confirmFrpInstallationFails() {
try {
- setSecureSetting("secure_frp_mode", 1)
+ setSecureFrp(true)
try {
val installation = startInstallationViaSession()
@@ -111,7 +111,7 @@
// Install should never have started
assertNotInstalled()
} finally {
- setSecureSetting("secure_frp_mode", 0)
+ setSecureFrp(false)
}
}
}
diff --git a/tests/tests/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
index dac484b..dd37ac9 100644
--- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml
+++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
@@ -15,205 +15,340 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- package="com.android.car"
- coreApp="true"
- android:sharedUserId="android.uid.system">
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ package="com.android.car"
+ coreApp="true"
+ android:sharedUserId="android.uid.system">
- <original-package android:name="com.android.car" />
- <permission-group
- android:name="android.car.permission-group.CAR_MONITORING"
- android:icon="@drawable/perm_group_car"
- android:description="@string/car_permission_desc"
- android:label="@string/car_permission_label" />
- <permission
- android:name="android.car.permission.CAR_ENERGY"
- android:permissionGroup="android.car.permission-group.CAR_MONITORING"
- android:protectionLevel="dangerous"
- android:label="@string/car_permission_label_energy"
- android:description="@string/car_permission_desc_energy" />
- <permission
- android:name="android.car.permission.CAR_IDENTIFICATION"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_car_identification"
- android:description="@string/car_permission_desc_car_identification" />
- <permission
- android:name="android.car.permission.CONTROL_CAR_CLIMATE"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_hvac"
- android:description="@string/car_permission_desc_hvac" />
- <permission
- android:name="android.car.permission.CONTROL_CAR_DOORS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_control_car_doors"
- android:description="@string/car_permission_desc_control_car_doors" />
- <permission
- android:name="android.car.permission.CONTROL_CAR_WINDOWS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_control_car_windows"
- android:description="@string/car_permission_desc_control_car_windows" />
- <permission
- android:name="android.car.permission.CONTROL_CAR_MIRRORS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_control_car_mirrors"
- android:description="@string/car_permission_desc_control_car_mirrors" />
- <permission
- android:name="android.car.permission.CONTROL_CAR_SEATS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_control_car_seats"
- android:description="@string/car_permission_desc_control_car_seats" />
- <permission
- android:name="android.car.permission.CAR_MILEAGE"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_mileage"
- android:description="@string/car_permission_desc_mileage" />
- <permission
- android:name="android.car.permission.CAR_TIRES"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_car_tires"
- android:description="@string/car_permission_desc_car_tires" />
- <permission
- android:name="android.car.permission.READ_CAR_STEERING"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_car_steering"
- android:description="@string/car_permission_desc_car_steering" />
- <permission
- android:name="android.car.permission.READ_CAR_DISPLAY_UNITS"
- android:protectionLevel="normal"
- android:label="@string/car_permission_label_read_car_display_units"
- android:description="@string/car_permission_desc_read_car_display_units" />
- <permission
- android:name="android.car.permission.CONTROL_CAR_DISPLAY_UNITS"
- android:protectionLevel="normal"
- android:label="@string/car_permission_label_control_car_display_units"
- android:description="@string/car_permission_desc_control_car_display_units" />
- <permission
- android:name="android.car.permission.CAR_SPEED"
- android:permissionGroup="android.permission-group.LOCATION"
- android:protectionLevel="dangerous"
- android:label="@string/car_permission_label_speed"
- android:description="@string/car_permission_desc_speed" />
- <permission
- android:name="android.car.permission.CAR_ENERGY_PORTS"
- android:protectionLevel="normal"
- android:label="@string/car_permission_label_car_energy_ports"
- android:description="@string/car_permission_desc_car_energy_ports" />
- <permission
- android:name="android.car.permission.CAR_ENGINE_DETAILED"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_car_engine_detailed"
- android:description="@string/car_permission_desc_car_engine_detailed" />
- <permission
- android:name="android.car.permission.CAR_DYNAMICS_STATE"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_vehicle_dynamics_state"
- android:description="@string/car_permission_desc_vehicle_dynamics_state" />
- <permission
- android:name="android.car.permission.CAR_VENDOR_EXTENSION"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_vendor_extension"
- android:description="@string/car_permission_desc_vendor_extension" />
- <permission
- android:name="android.car.permission.CAR_PROJECTION"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_projection"
- android:description="@string/car_permission_desc_projection" />
- <permission
- android:name="android.car.permission.ACCESS_CAR_PROJECTION_STATUS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_access_projection_status"
- android:description="@string/car_permission_desc_access_projection_status" />
- <permission
- android:name="android.car.permission.BIND_PROJECTION_SERVICE"
- android:protectionLevel="signature"
- android:label="@string/car_permission_label_bind_projection_service"
- android:description="@string/car_permission_desc_bind_projection_service" />
- <permission
- android:name="android.car.permission.CAR_MOCK_VEHICLE_HAL"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_mock_vehicle_hal"
- android:description="@string/car_permission_desc_mock_vehicle_hal" />
- <permission
- android:name="android.car.permission.CAR_INFO"
- android:protectionLevel="normal"
- android:label="@string/car_permission_label_car_info"
- android:description="@string/car_permission_desc_car_info" />
- <permission
- android:name="android.car.permission.CAR_EXTERIOR_ENVIRONMENT"
- android:protectionLevel="normal"
- android:label="@string/car_permission_label_car_exterior_environment"
- android:description="@string/car_permission_desc_car_exterior_environment" />
- <permission
- android:name="android.car.permission.CAR_EXTERIOR_LIGHTS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_car_exterior_lights"
- android:description="@string/car_permission_desc_car_exterior_lights" />
- <permission
- android:name="android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_control_car_exterior_lights"
- android:description="@string/car_permission_desc_control_car_exterior_lights" />
- <permission
- android:name="android.car.permission.READ_CAR_INTERIOR_LIGHTS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_car_interior_lights"
- android:description="@string/car_permission_desc_car_interior_lights" />
- <permission
- android:name="android.car.permission.CONTROL_CAR_INTERIOR_LIGHTS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_control_car_interior_lights"
- android:description="@string/car_permission_desc_control_car_interior_lights" />
- <permission
- android:name="android.car.permission.CAR_POWER"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_car_power"
- android:description="@string/car_permission_desc_car_power" />
- <permission
- android:name="android.car.permission.CAR_POWERTRAIN"
- android:protectionLevel="normal"
- android:label="@string/car_permission_label_car_powertrain"
- android:description="@string/car_permission_desc_car_powertrain" />
- <permission
- android:name="android.car.permission.CAR_NAVIGATION_MANAGER"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_car_navigation_manager"
- android:description="@string/car_permission_desc_car_navigation_manager" />
- <permission
- android:name="android.car.permission.CAR_DIAGNOSTICS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_diag_read"
- android:description="@string/car_permission_desc_diag_read" />
- <permission
- android:name="android.car.permission.CLEAR_CAR_DIAGNOSTICS"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_diag_clear"
- android:description="@string/car_permission_desc_diag_clear" />
- <permission
- android:name="android.car.permission.BIND_VMS_CLIENT"
- android:protectionLevel="signature"
- android:label="@string/car_permission_label_bind_vms_client"
- android:description="@string/car_permission_desc_bind_vms_client" />
- <permission
- android:name="android.car.permission.VMS_PUBLISHER"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_vms_publisher"
- android:description="@string/car_permission_desc_vms_publisher" />
- <permission
- android:name="android.car.permission.VMS_SUBSCRIBER"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_vms_subscriber"
- android:description="@string/car_permission_desc_vms_subscriber" />
- <permission
- android:name="android.car.permission.CAR_DRIVING_STATE"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_driving_state"
- android:description="@string/car_permission_desc_driving_state" />
+ <original-package android:name="com.android.car"/>
+ <permission-group android:name="android.car.permission-group.CAR_MONITORING"
+ android:icon="@drawable/perm_group_car"
+ android:description="@string/car_permission_desc"
+ android:label="@string/car_permission_label"/>
+ <permission android:name="android.car.permission.CAR_ENERGY"
+ android:permissionGroup="android.car.permission-group.CAR_MONITORING"
+ android:protectionLevel="dangerous"
+ android:label="@string/car_permission_label_energy"
+ android:description="@string/car_permission_desc_energy"/>
+ <permission android:name="android.car.permission.CAR_IDENTIFICATION"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_identification"
+ android:description="@string/car_permission_desc_car_identification"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_CLIMATE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_hvac"
+ android:description="@string/car_permission_desc_hvac"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_DOORS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_doors"
+ android:description="@string/car_permission_desc_control_car_doors"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_WINDOWS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_windows"
+ android:description="@string/car_permission_desc_control_car_windows"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_MIRRORS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_mirrors"
+ android:description="@string/car_permission_desc_control_car_mirrors"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_SEATS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_seats"
+ android:description="@string/car_permission_desc_control_car_seats"/>
+ <permission android:name="android.car.permission.CAR_MILEAGE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_mileage"
+ android:description="@string/car_permission_desc_mileage"/>
+ <permission android:name="android.car.permission.CAR_TIRES"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_tires"
+ android:description="@string/car_permission_desc_car_tires"/>
+ <permission android:name="android.car.permission.READ_CAR_STEERING"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_steering"
+ android:description="@string/car_permission_desc_car_steering"/>
+ <permission android:name="android.car.permission.READ_CAR_DISPLAY_UNITS"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_read_car_display_units"
+ android:description="@string/car_permission_desc_read_car_display_units"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_DISPLAY_UNITS"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_control_car_display_units"
+ android:description="@string/car_permission_desc_control_car_display_units"/>
+ <permission android:name="android.car.permission.CAR_SPEED"
+ android:permissionGroup="android.permission-group.LOCATION"
+ android:protectionLevel="dangerous"
+ android:label="@string/car_permission_label_speed"
+ android:description="@string/car_permission_desc_speed"/>
+ <permission android:name="android.car.permission.CAR_ENERGY_PORTS"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_energy_ports"
+ android:description="@string/car_permission_desc_car_energy_ports"/>
+ <permission android:name="android.car.permission.CAR_ENGINE_DETAILED"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_engine_detailed"
+ android:description="@string/car_permission_desc_car_engine_detailed"/>
+ <permission android:name="android.car.permission.CAR_DYNAMICS_STATE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_vehicle_dynamics_state"
+ android:description="@string/car_permission_desc_vehicle_dynamics_state"/>
+ <permission android:name="android.car.permission.CAR_VENDOR_EXTENSION"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_vendor_extension"
+ android:description="@string/car_permission_desc_vendor_extension"/>
+ <permission android:name="android.car.permission.CAR_PROJECTION"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_projection"
+ android:description="@string/car_permission_desc_projection"/>
+ <permission android:name="android.car.permission.ACCESS_CAR_PROJECTION_STATUS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_access_projection_status"
+ android:description="@string/car_permission_desc_access_projection_status"/>
+ <permission android:name="android.car.permission.BIND_PROJECTION_SERVICE"
+ android:protectionLevel="signature"
+ android:label="@string/car_permission_label_bind_projection_service"
+ android:description="@string/car_permission_desc_bind_projection_service"/>
+ <permission android:name="android.car.permission.CAR_MOCK_VEHICLE_HAL"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_mock_vehicle_hal"
+ android:description="@string/car_permission_desc_mock_vehicle_hal"/>
+ <permission android:name="android.car.permission.CAR_INFO"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_info"
+ android:description="@string/car_permission_desc_car_info"/>
+ <permission android:name="android.car.permission.CAR_EXTERIOR_ENVIRONMENT"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_exterior_environment"
+ android:description="@string/car_permission_desc_car_exterior_environment"/>
+ <permission android:name="android.car.permission.CAR_EXTERIOR_LIGHTS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_exterior_lights"
+ android:description="@string/car_permission_desc_car_exterior_lights"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_exterior_lights"
+ android:description="@string/car_permission_desc_control_car_exterior_lights"/>
+ <permission android:name="android.car.permission.READ_CAR_INTERIOR_LIGHTS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_interior_lights"
+ android:description="@string/car_permission_desc_car_interior_lights"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_INTERIOR_LIGHTS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_interior_lights"
+ android:description="@string/car_permission_desc_control_car_interior_lights"/>
+ <permission android:name="android.car.permission.CAR_POWER"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_power"
+ android:description="@string/car_permission_desc_car_power"/>
+ <permission android:name="android.car.permission.CAR_POWERTRAIN"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_powertrain"
+ android:description="@string/car_permission_desc_car_powertrain"/>
+ <permission android:name="android.car.permission.CAR_NAVIGATION_MANAGER"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_car_navigation_manager"
+ android:description="@string/car_permission_desc_car_navigation_manager"/>
+ <permission android:name="android.car.permission.CAR_DIAGNOSTICS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_diag_read"
+ android:description="@string/car_permission_desc_diag_read"/>
+ <permission android:name="android.car.permission.CLEAR_CAR_DIAGNOSTICS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_diag_clear"
+ android:description="@string/car_permission_desc_diag_clear"/>
+ <permission android:name="android.car.permission.BIND_VMS_CLIENT"
+ android:protectionLevel="signature"
+ android:label="@string/car_permission_label_bind_vms_client"
+ android:description="@string/car_permission_desc_bind_vms_client"/>
+ <permission android:name="android.car.permission.VMS_PUBLISHER"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_vms_publisher"
+ android:description="@string/car_permission_desc_vms_publisher"/>
+ <permission android:name="android.car.permission.VMS_SUBSCRIBER"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_vms_subscriber"
+ android:description="@string/car_permission_desc_vms_subscriber"/>
+ <permission android:name="android.car.permission.CAR_DRIVING_STATE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_driving_state"
+ android:description="@string/car_permission_desc_driving_state"/>
<!-- may replace this with system permission if proper one is defined. -->
- <permission
- android:name="android.car.permission.CONTROL_APP_BLOCKING"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_control_app_blocking"
- android:description="@string/car_permission_desc_control_app_blocking" />
+ <permission android:name="android.car.permission.CONTROL_APP_BLOCKING"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_app_blocking"
+ android:description="@string/car_permission_desc_control_app_blocking"/>
+ <permission android:name="android.car.permission.ADJUST_RANGE_REMAINING"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_adjust_range_remaining"
+ android:description="@string/car_permission_desc_adjust_range_remaining"/>
+ <permission android:name="android.car.permission.READ_CAR_OCCUPANT_AWARENESS_STATE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_read_car_occupant_awareness_state"
+ android:description="@string/car_permission_desc_read_car_occupant_awareness_state"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_ENERGY_PORTS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_energy_ports"
+ android:description="@string/car_permission_desc_control_car_energy_ports"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_OCCUPANT_AWARENESS_SYSTEM"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_occupant_awareness_system"
+ android:description="@string/car_permission_desc_control_car_occupant_awareness_system"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_FEATURES"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_features"
+ android:description="@string/car_permission_desc_control_car_features"/>
+ <permission android:name="android.car.permission.USE_CAR_WATCHDOG"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_use_car_watchdog"
+ android:description="@string/car_permission_desc_use_car_watchdog"/>
+ <permission android:name="android.car.permission.READ_CAR_VENDOR_PERMISSION_INFO"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_vendor_permission_info"
+ android:description="@string/car_permission_desc_vendor_permission_info"/>
+ <!-- Permission for vendor properties -->
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_WINDOW"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_window"
+ android:description="@string/car_permission_desc_get_car_vendor_category_window"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_WINDOW"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_window"
+ android:description="@string/car_permission_desc_set_car_vendor_category_window"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_DOOR"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_door"
+ android:description="@string/car_permission_desc_get_car_vendor_category_door"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_DOOR"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_door"
+ android:description="@string/car_permission_desc_set_car_vendor_category_door"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_SEAT"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_seat"
+ android:description="@string/car_permission_desc_get_car_vendor_category_seat"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_SEAT"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_seat"
+ android:description="@string/car_permission_desc_set_car_vendor_category_seat"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_MIRROR"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_mirror"
+ android:description="@string/car_permission_desc_get_car_vendor_category_mirror"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_MIRROR"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_mirror"
+ android:description="@string/car_permission_desc_set_car_vendor_category_mirror"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_INFO"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_info"
+ android:description="@string/car_permission_desc_get_car_vendor_category_info"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_INFO"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_info"
+ android:description="@string/car_permission_desc_set_car_vendor_category_info"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_ENGINE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_engine"
+ android:description="@string/car_permission_desc_get_car_vendor_category_engine"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_ENGINE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_engine"
+ android:description="@string/car_permission_desc_set_car_vendor_category_engine"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_HVAC"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_hvac"
+ android:description="@string/car_permission_desc_get_car_vendor_category_hvac"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_HVAC"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_hvac"
+ android:description="@string/car_permission_desc_set_car_vendor_category_hvac"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_LIGHT"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_light"
+ android:description="@string/car_permission_desc_get_car_vendor_category_light"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_LIGHT"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_light"
+ android:description="@string/car_permission_desc_set_car_vendor_category_light"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_1"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_1"
+ android:description="@string/car_permission_desc_get_car_vendor_category_1"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_1"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_1"
+ android:description="@string/car_permission_desc_set_car_vendor_category_1"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_2"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_2"
+ android:description="@string/car_permission_desc_get_car_vendor_category_2"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_2"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_2"
+ android:description="@string/car_permission_desc_set_car_vendor_category_2"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_3"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_3"
+ android:description="@string/car_permission_desc_get_car_vendor_category_3"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_3"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_3"
+ android:description="@string/car_permission_desc_set_car_vendor_category_3"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_4"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_4"
+ android:description="@string/car_permission_desc_get_car_vendor_category_4"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_4"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_4"
+ android:description="@string/car_permission_desc_set_car_vendor_category_4"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_5"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_5"
+ android:description="@string/car_permission_desc_get_car_vendor_category_5"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_5"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_5"
+ android:description="@string/car_permission_desc_set_car_vendor_category_5"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_6"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_6"
+ android:description="@string/car_permission_desc_get_car_vendor_category_6"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_6"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_6"
+ android:description="@string/car_permission_desc_set_car_vendor_category_6"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_7"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_7"
+ android:description="@string/car_permission_desc_get_car_vendor_category_7"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_7"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_7"
+ android:description="@string/car_permission_desc_set_car_vendor_category_7"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_8"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_8"
+ android:description="@string/car_permission_desc_get_car_vendor_category_8"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_8"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_8"
+ android:description="@string/car_permission_desc_set_car_vendor_category_8"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_9"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_9"
+ android:description="@string/car_permission_desc_get_car_vendor_category_9"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_9"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_9"
+ android:description="@string/car_permission_desc_set_car_vendor_category_9"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_10"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_10"
+ android:description="@string/car_permission_desc_get_car_vendor_category_10"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_10"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_10"
+ android:description="@string/car_permission_desc_set_car_vendor_category_10"/>
<permission
android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"
diff --git a/tests/tests/provider/res/raw/moov-at-end-zero-len.mp4 b/tests/tests/provider/res/raw/moov-at-end-zero-len.mp4
new file mode 100644
index 0000000..5b307e2
--- /dev/null
+++ b/tests/tests/provider/res/raw/moov-at-end-zero-len.mp4
Binary files differ
diff --git a/tests/tests/provider/res/raw/moov-at-end.mp4 b/tests/tests/provider/res/raw/moov-at-end.mp4
new file mode 100644
index 0000000..cdf74b5
--- /dev/null
+++ b/tests/tests/provider/res/raw/moov-at-end.mp4
Binary files differ
diff --git a/tests/tests/provider/res/raw/testvideo_meta.mp4 b/tests/tests/provider/res/raw/testvideo_meta.mp4
index 8f04b40..e83c61d 100644
--- a/tests/tests/provider/res/raw/testvideo_meta.mp4
+++ b/tests/tests/provider/res/raw/testvideo_meta.mp4
Binary files differ
diff --git a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
index feeb87c..942d4f4 100644
--- a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
@@ -22,8 +22,10 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.app.AppOpsManager;
import android.app.UiAutomation;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -35,6 +37,7 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
@@ -252,11 +255,21 @@
if (userManager.isSystemUser() &&
FileUtils.contains(Environment.getStorageDirectory(), file)) {
executeShellCommand("mkdir -p " + file.getParent());
+ waitUntilExists(file.getParentFile());
try (AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId)) {
final File source = ParcelFileDescriptor.getFile(afd.getFileDescriptor());
final long skip = afd.getStartOffset();
final long count = afd.getLength();
+ try {
+ // Try to create the file as calling package so that calling package remains
+ // as owner of the file.
+ file.createNewFile();
+ } catch (IOException ignored) {
+ // Apps can't create files in other app's private directories, but shell can. If
+ // file creation fails, we ignore and let `dd` command create it instead.
+ }
+
executeShellCommand(String.format("dd bs=1 if=%s skip=%d count=%d of=%s",
source.getAbsolutePath(), skip, count, file.getAbsolutePath()));
@@ -471,4 +484,31 @@
throw new IllegalArgumentException();
}
}
+
+ /** Revokes ACCESS_MEDIA_LOCATION from the test app */
+ public static void revokeMediaLocationPermission(Context context) throws Exception {
+ try {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity("android.permission.MANAGE_APP_OPS_MODES",
+ "android.permission.REVOKE_RUNTIME_PERMISSIONS");
+
+ // Revoking ACCESS_MEDIA_LOCATION permission will kill the test app.
+ // Deny access_media_permission App op to revoke this permission.
+ PackageManager packageManager = context.getPackageManager();
+ String packageName = context.getPackageName();
+ if (packageManager.checkPermission(android.Manifest.permission.ACCESS_MEDIA_LOCATION,
+ packageName) == PackageManager.PERMISSION_GRANTED) {
+ context.getPackageManager().updatePermissionFlags(
+ android.Manifest.permission.ACCESS_MEDIA_LOCATION, packageName,
+ PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
+ PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, context.getUser());
+ context.getSystemService(AppOpsManager.class).setUidMode(
+ "android:access_media_location", Process.myUid(),
+ AppOpsManager.MODE_IGNORED);
+ }
+ } finally {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().
+ dropShellPermissionIdentity();
+ }
+ }
}
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_MediaTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_MediaTest.java
index df47fac..1d18a8a 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_MediaTest.java
@@ -25,12 +25,10 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.app.AppOpsManager;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -40,7 +38,6 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
-import android.os.Process;
import android.os.storage.StorageManager;
import android.provider.BaseColumns;
import android.provider.MediaStore;
@@ -300,8 +297,6 @@
*/
@Test
public void testUpdateAndReplace() throws Exception {
- Assume.assumeFalse(mVolumeName.equals(MediaStore.VOLUME_EXTERNAL));
-
File dir = mContext.getSystemService(StorageManager.class)
.getStorageVolume(mExternalImages).getDirectory();
File dcimDir = new File(dir, Environment.DIRECTORY_DCIM);
@@ -339,8 +334,6 @@
@Test
public void testUpsert() throws Exception {
- Assume.assumeFalse(mVolumeName.equals(MediaStore.VOLUME_EXTERNAL));
-
File dir = mContext.getSystemService(StorageManager.class)
.getStorageVolume(mExternalImages).getDirectory();
File dcimDir = new File(dir, Environment.DIRECTORY_DCIM);
@@ -395,30 +388,12 @@
assertNotNull(mContentResolver.loadThumbnail(uri, new Size(96, 96), null));
}
- /**
- * This test doesn't hold
- * {@link android.Manifest.permission#ACCESS_MEDIA_LOCATION}, so Exif
- * location information should be redacted.
- */
@Test
public void testLocationRedaction() throws Exception {
// STOPSHIP: remove this once isolated storage is always enabled
Assume.assumeTrue(StorageManager.hasIsolatedStorage());
-
- final String displayName = "cts" + System.nanoTime();
- final PendingParams params = new PendingParams(
- mExternalImages, displayName, "image/jpeg");
-
- final Uri pendingUri = MediaStoreUtils.createPending(mContext, params);
- final Uri publishUri;
- try (PendingSession session = MediaStoreUtils.openPending(mContext, pendingUri)) {
- try (InputStream in = mContext.getResources().openRawResource(R.raw.lg_g4_iso_800_jpg);
- OutputStream out = session.openOutputStream()) {
- android.os.FileUtils.copy(in, out);
- }
- publishUri = session.publish();
- }
-
+ final Uri publishUri = ProviderTestUtils.stageMedia(R.raw.lg_g4_iso_800_jpg, mExternalImages,
+ "image/jpeg");
final Uri originalUri = MediaStore.setRequireOriginal(publishUri);
// Since we own the image, we should be able to see the Exif data that
@@ -439,32 +414,8 @@
try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(originalUri, "r")) {
}
- // Remove ACCESS_MEDIA_LOCATION permission
- try {
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .adoptShellPermissionIdentity("android.permission.MANAGE_APP_OPS_MODES",
- "android.permission.REVOKE_RUNTIME_PERMISSIONS");
-
- // Revoking ACCESS_MEDIA_LOCATION permission will kill the test app.
- // Deny access_media_permission App op to revoke this permission.
- PackageManager packageManager = mContext.getPackageManager();
- String packageName = mContext.getPackageName();
- if (packageManager.checkPermission(android.Manifest.permission.ACCESS_MEDIA_LOCATION,
- packageName) == PackageManager.PERMISSION_GRANTED) {
- mContext.getPackageManager().updatePermissionFlags(
- android.Manifest.permission.ACCESS_MEDIA_LOCATION, packageName,
- PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
- PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, mContext.getUser());
- mContext.getSystemService(AppOpsManager.class).setUidMode(
- "android:access_media_location", Process.myUid(),
- AppOpsManager.MODE_IGNORED);
- }
- } finally {
- InstrumentationRegistry.getInstrumentation().getUiAutomation().
- dropShellPermissionIdentity();
- }
-
- // Now remove ownership, which means that Exif/XMP location data should be redacted
+ // Revoke location access and remove ownership, which means that location should be redacted
+ ProviderTestUtils.revokeMediaLocationPermission(mContext);
ProviderTestUtils.clearOwner(publishUri);
try (InputStream is = mContentResolver.openInputStream(publishUri)) {
final ExifInterface exif = new ExifInterface(is);
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_MediaTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_MediaTest.java
index dca7382..88295eb 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_MediaTest.java
@@ -27,19 +27,16 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.app.AppOpsManager;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.database.Cursor;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
-import android.os.Process;
import android.os.storage.StorageManager;
import android.provider.MediaStore;
import android.provider.MediaStore.Files.FileColumns;
@@ -203,41 +200,32 @@
return context.getContentResolver().insert(mExternalVideo, values);
}
- /**
- * This test doesn't hold
- * {@link android.Manifest.permission#ACCESS_MEDIA_LOCATION}, so Exif and XMP
- * location information should be redacted.
- */
@Test
- public void testLocationRedaction() throws Exception {
- // STOPSHIP: remove this once isolated storage is always enabled
- Assume.assumeTrue(StorageManager.hasIsolatedStorage());
-
- final String displayName = "cts" + System.nanoTime();
- final PendingParams params = new PendingParams(
- mExternalVideo, displayName, "video/mp4");
-
- final Uri pendingUri = MediaStoreUtils.createPending(mContext, params);
- final Uri publishUri;
- try (PendingSession session = MediaStoreUtils.openPending(mContext, pendingUri)) {
- try (InputStream in = mContext.getResources().openRawResource(R.raw.testvideo_meta);
- OutputStream out = session.openOutputStream()) {
- FileUtils.copy(in, out);
- }
- publishUri = session.publish();
- }
-
+ public void testOriginalAccess() throws Exception {
+ final Uri publishUri = ProviderTestUtils.stageMedia(R.raw.testvideo_meta, mExternalVideo,
+ "video/mp4");
final Uri originalUri = MediaStore.setRequireOriginal(publishUri);
- // Since we own the video, we should be able to see the location
- // we ourselves contributed
- try (ParcelFileDescriptor pfd = mContentResolver.openFile(publishUri, "r", null);
- MediaMetadataRetriever mmr = new MediaMetadataRetriever()) {
- mmr.setDataSource(pfd.getFileDescriptor());
- assertEquals("+37.4217-122.0834/",
- mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION));
- assertEquals("2", mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS));
+ // As owner, we should be able to request the original bytes
+ try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(originalUri, "r")) {
}
+
+ // Revoke location access and remove ownership, which means that location should be redacted
+ ProviderTestUtils.revokeMediaLocationPermission(mContext);
+ ProviderTestUtils.clearOwner(publishUri);
+
+ // We can't request original bytes unless we have permission
+ try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(originalUri, "r")) {
+ fail("Able to read original content without ACCESS_MEDIA_LOCATION");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+
+ @Test
+ public void testXmpLocationRedaction() throws Exception {
+ final Uri publishUri = ProviderTestUtils.stageMedia(R.raw.testvideo_meta, mExternalVideo,
+ "video/mp4");
+
try (InputStream in = mContentResolver.openInputStream(publishUri);
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
FileUtils.copy(in, out);
@@ -248,44 +236,11 @@
assertTrue("Failed to read XMP latitude", xmp.contains("53,50.070500N"));
assertTrue("Failed to read non-location XMP", xmp.contains("13166/7763"));
}
- // As owner, we should be able to request the original bytes
- try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(originalUri, "r")) {
- }
- // Remove ACCESS_MEDIA_LOCATION permission
- try {
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .adoptShellPermissionIdentity("android.permission.MANAGE_APP_OPS_MODES",
- "android.permission.REVOKE_RUNTIME_PERMISSIONS");
-
- // Revoking ACCESS_MEDIA_LOCATION permission will kill the test app.
- // Deny access_media_permission App op to revoke this permission.
- PackageManager packageManager = mContext.getPackageManager();
- String packageName = mContext.getPackageName();
- if (packageManager.checkPermission(android.Manifest.permission.ACCESS_MEDIA_LOCATION,
- packageName) == PackageManager.PERMISSION_GRANTED) {
- mContext.getPackageManager().updatePermissionFlags(
- android.Manifest.permission.ACCESS_MEDIA_LOCATION, packageName,
- PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
- PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, mContext.getUser());
- mContext.getSystemService(AppOpsManager.class).setUidMode(
- "android:access_media_location", Process.myUid(),
- AppOpsManager.MODE_IGNORED);
- }
- } finally {
- InstrumentationRegistry.getInstrumentation().getUiAutomation().
- dropShellPermissionIdentity();
- }
-
- // Now remove ownership, which means that location should be redacted
+ // Revoke location access and remove ownership, which means that location should be redacted
+ ProviderTestUtils.revokeMediaLocationPermission(mContext);
ProviderTestUtils.clearOwner(publishUri);
- try (ParcelFileDescriptor pfd = mContentResolver.openFile(publishUri, "r", null);
- MediaMetadataRetriever mmr = new MediaMetadataRetriever()) {
- mmr.setDataSource(pfd.getFileDescriptor());
- assertEquals(null,
- mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION));
- assertEquals("2", mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS));
- }
+
try (InputStream in = mContentResolver.openInputStream(publishUri);
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
FileUtils.copy(in, out);
@@ -296,10 +251,52 @@
assertFalse("Failed to redact XMP latitude", xmp.contains("53,50.070500N"));
assertTrue("Redacted non-location XMP", xmp.contains("13166/7763"));
}
- // We can't request original bytes unless we have permission
- try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(originalUri, "r")) {
- fail("Able to read original content without ACCESS_MEDIA_LOCATION");
- } catch (UnsupportedOperationException expected) {
+ }
+
+ @Test
+ public void testIsoLocationRedaction() throws Exception {
+ // STOPSHIP: remove this once isolated storage is always enabled
+ Assume.assumeTrue(StorageManager.hasIsolatedStorage());
+
+ // These videos have all had their ISO location metadata (in the (c)xyz box) artificially
+ // modified to +58.0000+011.0000 (middle of Skagerrak).
+ int[] videoIds = new int[] {
+ R.raw.testvideo_meta,
+ R.raw.moov_at_end,
+ R.raw.moov_at_end_zero_len,
+ };
+ Uri[] uris = new Uri[videoIds.length];
+ for (int i = 0; i < videoIds.length; i++) {
+ uris[i] = ProviderTestUtils.stageMedia(videoIds[i], mExternalVideo, "video/mp4");
+ }
+
+ for (int i = 0; i < uris.length; i++) {
+ // Since we own the video, we should be able to see the location
+ // we ourselves contributed
+ try (ParcelFileDescriptor pfd = mContentResolver.openFile(uris[i], "r", null);
+ MediaMetadataRetriever mmr = new MediaMetadataRetriever()) {
+ mmr.setDataSource(pfd.getFileDescriptor());
+ assertEquals("+58.0000+011.0000/",
+ mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION));
+ assertEquals("2",
+ mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS));
+ }
+ }
+
+ // Revoke location access and remove ownership, which means that location should be redacted
+ ProviderTestUtils.revokeMediaLocationPermission(mContext);
+
+ for (int i = 0; i < uris.length; i++) {
+ ProviderTestUtils.clearOwner(uris[i]);
+
+ try (ParcelFileDescriptor pfd = mContentResolver.openFile(uris[i], "r", null);
+ MediaMetadataRetriever mmr = new MediaMetadataRetriever()) {
+ mmr.setDataSource(pfd.getFileDescriptor());
+ assertEquals(null,
+ mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION));
+ assertEquals("2",
+ mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS));
+ }
}
}
diff --git a/tests/tests/secure_element/omapi/apk/signed-CtsOmapiTestCases.apk b/tests/tests/secure_element/omapi/apk/signed-CtsOmapiTestCases.apk
index a6cbfd8..53275fd 100644
--- a/tests/tests/secure_element/omapi/apk/signed-CtsOmapiTestCases.apk
+++ b/tests/tests/secure_element/omapi/apk/signed-CtsOmapiTestCases.apk
Binary files differ
diff --git a/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java
index 8c2f870..f5ddc7c 100644
--- a/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java
+++ b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java
@@ -314,7 +314,12 @@
*/
public void showsExtraChooserTargets() {
// Should show chooser targets but must limit them, can't test limit here
- waitAndAssertTextContains(mExtraChooserTargetsLabelBase);
+ if (mActivityManager.isLowRamDevice()) {
+ // The direct share row and EXTRA_CHOOSER_TARGETS should be hidden on low-ram devices
+ waitAndAssertNoTextContains(mExtraChooserTargetsLabelBase);
+ } else {
+ waitAndAssertTextContains(mExtraChooserTargetsLabelBase);
+ }
}
/**
diff --git a/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java b/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java
index fe35f73..f31dcf1 100644
--- a/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java
+++ b/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java
@@ -30,7 +30,10 @@
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.google.common.truth.Expect;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -52,6 +55,8 @@
}
}
+ @Rule public final Expect mExpect = Expect.create();
+
private Context mContext;
private PackageManager mPackageManager;
@@ -114,7 +119,8 @@
if ((productFlags & e.flags) == 0) {
final ResolveInfo ri = mPackageManager.resolveActivity(e.intent,
PackageManager.MATCH_DEFAULT_ONLY);
- assertTrue("API intent " + e.intent + " not implemented by any activity", ri != null);
+ mExpect.withMessage("API intent %s not implemented by any activity", e.intent)
+ .that(ri).isNotNull();
}
}
}
diff --git a/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp b/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
index ab4ce58..fbf9f9a 100644
--- a/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
+++ b/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
@@ -408,16 +408,25 @@
Callback* cb64 = new Callback("cb64");
auto start = now();
+ auto vsyncPeriod = std::chrono::duration_cast<std::chrono::milliseconds>(
+ NOMINAL_VSYNC_PERIOD)
+ .count();
auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
AChoreographer_postFrameCallbackDelayed(choreographer, frameCallback, cb1, delay);
AChoreographer_postFrameCallbackDelayed64(choreographer, frameCallback64, cb64, delay);
std::this_thread::sleep_for(DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 10);
- ALooper_pollAll(16, nullptr, nullptr, nullptr);
+ // Ensure that callbacks are seen by the looper instance at approximately
+ // the same time, and provide enough time for the looper instance to process
+ // the delayed callback and the requested vsync signal if needed.
+ ALooper_pollAll(vsyncPeriod * 5, nullptr, nullptr, nullptr);
verifyRefreshRateCallback(env, cb, 1);
- verifyCallback(env, cb64, 1, start, DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 11);
+ verifyCallback(env, cb64, 1, start,
+ DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 15);
const auto delayToTestFor32Bit =
- sizeof(long) == sizeof(int64_t) ? DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 11 : ZERO;
+ sizeof(long) == sizeof(int64_t)
+ ? DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 15
+ : ZERO;
verifyCallback(env, cb1, 1, start, delayToTestFor32Bit);
AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, cb);
}
diff --git a/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java b/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java
index 66b1539..7ab5143 100644
--- a/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java
@@ -19,6 +19,7 @@
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
+import static android.opengl.GLES20.glFinish;
import android.app.Activity;
import android.content.pm.ActivityInfo;
@@ -258,6 +259,7 @@
int surfaceUpdateCount = mSurfaceUpdatedCount;
runOnGLThread(() -> {
callback.drawFrame(mSurfaceWidth, mSurfaceHeight);
+ glFinish();
if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
throw new RuntimeException("Cannot swap buffers");
}
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiFeature.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiFeature.java
index 3e9fef4..4876ff0 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiFeature.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiFeature.java
@@ -29,4 +29,9 @@
PackageManager packageManager = context.getPackageManager();
return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT);
}
+
+ public static boolean isTelephonySupported(Context context) {
+ final PackageManager pm = context.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+ }
}
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index 199e856..8ad29c7 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -2312,9 +2312,11 @@
// assert that the country code is all uppercase
assertEquals(wifiCountryCode.toUpperCase(Locale.US), wifiCountryCode);
- String telephonyCountryCode = getContext().getSystemService(TelephonyManager.class)
- .getNetworkCountryIso();
- assertEquals(telephonyCountryCode, wifiCountryCode.toLowerCase(Locale.US));
+ if (WifiFeature.isTelephonySupported(getContext())) {
+ String telephonyCountryCode = getContext().getSystemService(TelephonyManager.class)
+ .getNetworkCountryIso();
+ assertEquals(telephonyCountryCode, wifiCountryCode.toLowerCase(Locale.US));
+ }
}
/**