Merge "Re-enable PowerStatsTestsRavenwood" into main
diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
index 33f6899..ecb9a73 100644
--- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
+++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
@@ -444,8 +444,13 @@
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- switch (intent.getAction()) {
+ switch (action) {
case Intent.ACTION_USER_REMOVED:
if (userId > 0) {
mHandler.doUserRemoved(userId);
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index a37779e..3e650da 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -666,7 +666,12 @@
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
- switch (intent.getAction()) {
+ final String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+
+ switch (action) {
case ConnectivityManager.CONNECTIVITY_ACTION: {
updateConnectivityState(intent);
} break;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index e3ac780..7a21697 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -84,9 +84,13 @@
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+
final String pkgName = getPackageName(intent);
final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
- final String action = intent.getAction();
if (pkgUid == -1) {
Slog.e(TAG, "Didn't get package UID in intent (" + action + ")");
return;
diff --git a/core/api/current.txt b/core/api/current.txt
index 2c4c146..6b342a5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -16232,6 +16232,7 @@
field public static final int UNKNOWN = 0; // 0x0
field public static final int Y8 = 538982489; // 0x20203859
field public static final int YCBCR_P010 = 54; // 0x36
+ field @FlaggedApi("android.media.codec.p210_format_support") public static final int YCBCR_P210 = 60; // 0x3c
field public static final int YUV_420_888 = 35; // 0x23
field public static final int YUV_422_888 = 39; // 0x27
field public static final int YUV_444_888 = 40; // 0x28
@@ -18580,6 +18581,7 @@
field public static final long USAGE_VIDEO_ENCODE = 65536L; // 0x10000L
field public static final int YCBCR_420_888 = 35; // 0x23
field public static final int YCBCR_P010 = 54; // 0x36
+ field @FlaggedApi("android.media.codec.p210_format_support") public static final int YCBCR_P210 = 60; // 0x3c
}
@FlaggedApi("android.hardware.flags.overlayproperties_class_api") public final class OverlayProperties implements android.os.Parcelable {
@@ -22871,6 +22873,7 @@
field public static final int COLOR_FormatYUV444Flexible = 2135181448; // 0x7f444888
field @Deprecated public static final int COLOR_FormatYUV444Interleaved = 29; // 0x1d
field public static final int COLOR_FormatYUVP010 = 54; // 0x36
+ field @FlaggedApi("android.media.codec.p210_format_support") public static final int COLOR_FormatYUVP210 = 60; // 0x3c
field @Deprecated public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
field @Deprecated public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
field public static final String FEATURE_AdaptivePlayback = "adaptive-playback";
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
old mode 100644
new mode 100755
index 69c3bd3..0264f73
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -61,6 +61,8 @@
oneway void shutdown();
void executeShellCommandWithStderr(String command, in ParcelFileDescriptor sink,
in ParcelFileDescriptor source, in ParcelFileDescriptor stderrSink);
+ void executeShellCommandArrayWithStderr(in String[] command, in ParcelFileDescriptor sink,
+ in ParcelFileDescriptor source, in ParcelFileDescriptor stderrSink);
List<String> getAdoptedShellPermissions();
void addOverridePermissionState(int uid, String permission, int result);
void removeOverridePermissionState(int uid, String permission);
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
old mode 100644
new mode 100755
index 3c4bd9e..72db465
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -553,7 +553,12 @@
} catch (IOException exc) {
throw new RuntimeException("Error running shell command '" + command + "'", exc);
}
+ handleExecuteShellCommandProcess(process, sink, source, stderrSink);
+ }
+ private void handleExecuteShellCommandProcess(final java.lang.Process process,
+ final ParcelFileDescriptor sink, final ParcelFileDescriptor source,
+ final ParcelFileDescriptor stderrSink) {
// Read from process and write to pipe
final Thread readFromProcess;
if (sink != null) {
@@ -616,6 +621,26 @@
}
@Override
+ public void executeShellCommandArrayWithStderr(final String[] command,
+ final ParcelFileDescriptor sink, final ParcelFileDescriptor source,
+ final ParcelFileDescriptor stderrSink) throws RemoteException {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final java.lang.Process process;
+
+ try {
+ process = Runtime.getRuntime().exec(command);
+ } catch (IOException exc) {
+ throw new RuntimeException(
+ "Error running shell command '" + String.join(" ", command) + "'", exc);
+ }
+ handleExecuteShellCommandProcess(process, sink, source, stderrSink);
+ }
+
+ @Override
public void shutdown() {
synchronized (mLock) {
if (isConnectedLocked()) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bca30b4..8de86d5 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -146,6 +146,7 @@
* This exception is thrown when a given package, application, or component
* name cannot be found.
*/
+ @android.ravenwood.annotation.RavenwoodKeepWholeClass
public static class NameNotFoundException extends AndroidException {
public NameNotFoundException() {
}
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index ce0f9f59..0e73978 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -66,6 +66,7 @@
DS_FP32UI8,
S_UI8,
YCBCR_P010,
+ YCBCR_P210,
R_8,
R_16,
RG_1616,
@@ -111,6 +112,16 @@
* little-endian value, with the lower 6 bits set to zero.
*/
public static final int YCBCR_P010 = 0x36;
+ /**
+ * <p>Android YUV P210 format.</p>
+ *
+ * P210 is a 4:2:2 YCbCr semiplanar format comprised of a WxH Y plane
+ * followed by a WxH CbCr plane. Each sample is represented by a 16-bit
+ * little-endian value, with the lower 6 bits set to zero.
+ */
+ @FlaggedApi(android.media.codec.Flags.FLAG_P210_FORMAT_SUPPORT)
+ public static final int YCBCR_P210 = 0x3c;
+
/** Format: 8 bits red */
@FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_REQUESTED_FORMATS_V)
public static final int R_8 = 0x38;
diff --git a/core/java/android/net/vcn/OWNERS b/core/java/android/net/vcn/OWNERS
index 2441e77..937699a 100644
--- a/core/java/android/net/vcn/OWNERS
+++ b/core/java/android/net/vcn/OWNERS
@@ -1,7 +1,6 @@
set noparent
-benedictwong@google.com
-ckesting@google.com
evitayan@google.com
-junyin@google.com
nharold@google.com
+benedictwong@google.com #{LAST_RESORT_SUGGESTION}
+yangji@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/core/java/android/net/vcn/flags.aconfig b/core/java/android/net/vcn/flags.aconfig
index 5b30624..1adefe5 100644
--- a/core/java/android/net/vcn/flags.aconfig
+++ b/core/java/android/net/vcn/flags.aconfig
@@ -10,8 +10,26 @@
}
flag {
+ name: "mainline_vcn_module_api"
+ namespace: "vcn"
+ description: "Expose APIs from VCN for mainline migration"
+ is_exported: true
+ bug: "376339506"
+}
+
+flag {
name: "safe_mode_timeout_config"
namespace: "vcn"
description: "Feature flag for adjustable safe mode timeout"
bug: "317406085"
+}
+
+flag {
+ name: "fix_config_garbage_collection"
+ namespace: "vcn"
+ description: "Handle race condition in subscription change"
+ bug: "370862489"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
\ No newline at end of file
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 2acda8a..e402ddf 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -249,6 +249,10 @@
return isExperimentEnabled("profilesystemserver");
}
+ private static boolean shouldProfileBootClasspath() {
+ return isExperimentEnabled("profilebootclasspath");
+ }
+
/**
* Performs Zygote process initialization. Loads and initializes commonly used classes.
*
@@ -352,7 +356,7 @@
// If we are profiling the boot image, reset the Jit counters after preloading the
// classes. We want to preload for performance, and we can use method counters to
// infer what clases are used after calling resetJitCounters, for profile purposes.
- if (isExperimentEnabled("profilebootclasspath")) {
+ if (shouldProfileBootClasspath()) {
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ResetJitCounters");
VMRuntime.resetJitCounters();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
@@ -460,12 +464,28 @@
? String.join(":", systemServerClasspath, standaloneSystemServerJars)
: systemServerClasspath;
prepareSystemServerProfile(systemServerPaths);
+ try {
+ SystemProperties.set("debug.tracing.profile_system_server", "1");
+ } catch (RuntimeException e) {
+ Slog.e(TAG, "Failed to set debug.tracing.profile_system_server", e);
+ }
} catch (Exception e) {
Log.wtf(TAG, "Failed to set up system server profile", e);
}
}
}
+ // Zygote can't set system properties due to permission denied. We need to be in System
+ // Server to set system properties, so we do it here instead of the more natural place in
+ // preloadClasses.
+ if (shouldProfileBootClasspath()) {
+ try {
+ SystemProperties.set("debug.tracing.profile_boot_classpath", "1");
+ } catch (RuntimeException e) {
+ Slog.e(TAG, "Failed to set debug.tracing.profile_boot_classpath", e);
+ }
+ }
+
if (parsedArgs.mInvokeWith != null) {
String[] args = parsedArgs.mRemainingArgs;
// If we have a non-null system server class path, we'll have to duplicate the
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index cb3b64c..93d94c9 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -16,6 +16,7 @@
package android.graphics;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import java.lang.annotation.Retention;
@@ -41,6 +42,7 @@
Y8,
Y16,
YCBCR_P010,
+ YCBCR_P210,
NV16,
NV21,
YUY2,
@@ -206,6 +208,26 @@
public static final int YCBCR_P010 = 0x36;
/**
+ * <p>Android YUV P210 format.</p>
+ *
+ * P210 is a 4:2:2 YCbCr semiplanar format comprised of a WxH Y plane
+ * followed by a WxH CbCr plane. Each sample is represented by a 16-bit
+ * little-endian value, with the lower 6 bits set to zero.
+ *
+ * <p>For example, the {@link android.media.Image} object can provide data
+ * in this format from a {@link android.hardware.camera2.CameraDevice}
+ * through a {@link android.media.ImageReader} object if this format is
+ * supported by {@link android.hardware.camera2.CameraDevice}.</p>
+ *
+ * @see android.media.Image
+ * @see android.media.ImageReader
+ * @see android.hardware.camera2.CameraDevice
+ *
+ */
+ @FlaggedApi(android.media.codec.Flags.FLAG_P210_FORMAT_SUPPORT)
+ public static final int YCBCR_P210 = 0x3c;
+
+ /**
* YCbCr format, used for video.
*
* <p>For the {@link android.hardware.camera2} API, the {@link #YUV_420_888} format is
@@ -849,6 +871,8 @@
return 16;
case YCBCR_P010:
return 24;
+ case YCBCR_P210:
+ return 32;
case RAW_DEPTH10:
case RAW10:
return 10;
@@ -899,7 +923,9 @@
case JPEG_R:
return true;
}
-
+ if (android.media.codec.Flags.p210FormatSupport() && format == YCBCR_P210) {
+ return true;
+ }
return false;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/OWNERS
new file mode 100644
index 0000000..752d2fd
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/OWNERS
@@ -0,0 +1,2 @@
+# WM Shell sub-module dagger owners
+jorgegil@google.com
\ No newline at end of file
diff --git a/libs/hwui/platform/host/android/api-level.h b/libs/hwui/platform/host/android/api-level.h
deleted file mode 120000
index 4fb4784..0000000
--- a/libs/hwui/platform/host/android/api-level.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../../bionic/libc/include/android/api-level.h
\ No newline at end of file
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 8ff4305..3a19f46 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -462,6 +462,33 @@
@SuppressLint("AllUpper")
public static final int COLOR_FormatYUVP010 = 54;
+ /**
+ * P210 is 10-bit-per component 4:2:2 YCbCr semiplanar format.
+ * <p>
+ * This format uses 32 allocated bits per pixel with 20 bits of
+ * data per pixel. Chroma planes are subsampled by 2 both
+ * horizontally. Each chroma and luma component
+ * has 16 allocated bits in little-endian configuration with 10
+ * MSB of actual data.
+ *
+ * <pre>
+ * byte byte
+ * <--------- i --------> | <------ i + 1 ------>
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | UNUSED | Y/Cb/Cr |
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * 0 5 6 7 0 7
+ * bit
+ * </pre>
+ *
+ * Use this format with {@link Image}. This format corresponds
+ * to {@link android.graphics.ImageFormat#YCBCR_P210}.
+ * <p>
+ */
+ @SuppressLint("AllUpper")
+ @FlaggedApi(android.media.codec.Flags.FLAG_P210_FORMAT_SUPPORT)
+ public static final int COLOR_FormatYUVP210 = 60;
+
/** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
// COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference.
diff --git a/packages/Vcn/TEST_MAPPING b/packages/Vcn/TEST_MAPPING
new file mode 100644
index 0000000..bde88fe
--- /dev/null
+++ b/packages/Vcn/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "postsubmit": [
+ {
+ "name": "FrameworksVcnTests"
+ },
+ {
+ "name": "CtsVcnTestCases"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING
index 7fa0ef1..a1243e3 100644
--- a/ravenwood/TEST_MAPPING
+++ b/ravenwood/TEST_MAPPING
@@ -35,18 +35,18 @@
},
{
"name": "CarLibHostUnitTest",
- "host": true,
- "keywords": ["automotive_code_coverage"]
+ "keywords": ["automotive_code_coverage"],
+ "host": true
},
{
"name": "CarServiceHostUnitTest",
- "host": true,
- "keywords": ["automotive_code_coverage"]
+ "keywords": ["automotive_code_coverage"],
+ "host": true
},
{
"name": "CarSystemUIRavenTests",
- "host": true,
- "keywords": ["automotive_code_coverage"]
+ "keywords": ["automotive_code_coverage"],
+ "host": true
},
{
"name": "CtsAccountManagerTestCasesRavenwood",
@@ -65,6 +65,10 @@
"host": true
},
{
+ "name": "CtsDeviceConfigTestCasesRavenwood",
+ "host": true
+ },
+ {
"name": "CtsGraphicsTestCasesRavenwood",
"host": true
},
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
index 30a653d..66a6890 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
@@ -38,7 +38,6 @@
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.Filterable;
import org.junit.runner.manipulation.NoTestsRemainException;
-import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.Suite;
@@ -94,7 +93,7 @@
/** Keeps track of the runner on the current thread. */
private static final ThreadLocal<RavenwoodAwareTestRunner> sCurrentRunner = new ThreadLocal<>();
- static RavenwoodAwareTestRunner getCurrentRunner() {
+ private static RavenwoodAwareTestRunner getCurrentRunner() {
var runner = sCurrentRunner.get();
if (runner == null) {
throw new RuntimeException("Current test runner not set!");
@@ -102,11 +101,9 @@
return runner;
}
- private final Class<?> mTestJavaClass;
+ final Class<?> mTestJavaClass;
+ private final Runner mRealRunner;
private TestClass mTestClass = null;
- private Runner mRealRunner = null;
- private Description mDescription = null;
- private Throwable mExceptionInConstructor = null;
/**
* Stores internal states / methods associated with this runner that's only needed in
@@ -114,50 +111,37 @@
*/
final RavenwoodRunnerState mState = new RavenwoodRunnerState(this);
- public TestClass getTestClass() {
- return mTestClass;
- }
-
/**
* Constructor.
*/
public RavenwoodAwareTestRunner(Class<?> testClass) {
RavenwoodRuntimeEnvironmentController.globalInitOnce();
mTestJavaClass = testClass;
- try {
- /*
- * If the class has @DisabledOnRavenwood, then we'll delegate to
- * ClassSkippingTestRunner, which simply skips it.
- *
- * We need to do it before instantiating TestClass for b/367694651.
- */
- if (!RavenwoodEnablementChecker.shouldRunClassOnRavenwood(testClass, true)) {
- mRealRunner = new ClassSkippingTestRunner(testClass);
- mDescription = mRealRunner.getDescription();
- return;
- }
- mTestClass = new TestClass(testClass);
-
- Log.v(TAG, "RavenwoodAwareTestRunner starting for " + testClass.getCanonicalName());
-
- onRunnerInitializing();
-
- mRealRunner = instantiateRealRunner(mTestClass);
- mDescription = mRealRunner.getDescription();
- } catch (Throwable th) {
- // If we throw in the constructor, Tradefed may not report it and just ignore the class,
- // so record it and throw it when the test actually started.
- Log.e(TAG, "Fatal: Exception detected in constructor", th);
- mExceptionInConstructor = new RuntimeException("Exception detected in constructor",
- th);
- mDescription = Description.createTestDescription(testClass, "Constructor");
-
- // This is for testing if tradefed is fixed.
- if ("1".equals(System.getenv("RAVENWOOD_THROW_EXCEPTION_IN_TEST_RUNNER"))) {
- throw th;
- }
+ /*
+ * If the class has @DisabledOnRavenwood, then we'll delegate to
+ * ClassSkippingTestRunner, which simply skips it.
+ *
+ * We need to do it before instantiating TestClass for b/367694651.
+ */
+ if (!RavenwoodEnablementChecker.shouldRunClassOnRavenwood(testClass, true)) {
+ mRealRunner = new ClassSkippingTestRunner(testClass);
+ return;
}
+
+ mTestClass = new TestClass(testClass);
+
+ Log.v(TAG, "RavenwoodAwareTestRunner starting for " + testClass.getCanonicalName());
+
+ // This is needed to make AndroidJUnit4ClassRunner happy.
+ InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
+
+ // Hook point to allow more customization.
+ runAnnotatedMethodsOnRavenwood(RavenwoodTestRunnerInitializing.class, null);
+
+ mRealRunner = instantiateRealRunner(mTestClass);
+
+ mState.enterTestRunner();
}
@Override
@@ -165,23 +149,11 @@
return mRealRunner;
}
- /**
- * Run the bare minimum setup to initialize the wrapped runner.
- */
- // This method is called by the ctor, so never make it virtual.
- private void onRunnerInitializing() {
- // This is needed to make AndroidJUnit4ClassRunner happy.
- InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
-
- // Hook point to allow more customization.
- runAnnotatedMethodsOnRavenwood(RavenwoodTestRunnerInitializing.class, null);
- }
-
private void runAnnotatedMethodsOnRavenwood(Class<? extends Annotation> annotationClass,
Object instance) {
Log.v(TAG, "runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
- for (var method : getTestClass().getAnnotatedMethods(annotationClass)) {
+ for (var method : mTestClass.getAnnotatedMethods(annotationClass)) {
ensureIsPublicVoidMethod(method.getMethod(), /* isStatic=*/ instance == null);
var methodDesc = method.getDeclaringClass().getName() + "."
@@ -195,11 +167,6 @@
}
@Override
- public Description getDescription() {
- return mDescription;
- }
-
- @Override
public void run(RunNotifier realNotifier) {
final var notifier = new RavenwoodRunNotifier(realNotifier);
final var description = getDescription();
@@ -216,10 +183,6 @@
dumpDescription(description);
}
- if (maybeReportExceptionFromConstructor(notifier)) {
- return;
- }
-
// TODO(b/365976974): handle nested classes better
final boolean skipRunnerHook =
mRealRunnerTakesRunnerBuilder && mRealRunner instanceof Suite;
@@ -228,7 +191,7 @@
try {
if (!skipRunnerHook) {
try {
- mState.enterTestClass(description);
+ mState.enterTestClass();
} catch (Throwable th) {
notifier.reportBeforeTestFailure(description, th);
return;
@@ -251,18 +214,6 @@
}
}
- /** Throw the exception detected in the constructor, if any. */
- private boolean maybeReportExceptionFromConstructor(RunNotifier notifier) {
- if (mExceptionInConstructor == null) {
- return false;
- }
- notifier.fireTestStarted(mDescription);
- notifier.fireTestFailure(new Failure(mDescription, mExceptionInConstructor));
- notifier.fireTestFinished(mDescription);
-
- return true;
- }
-
private Statement wrapWithHooks(Statement base, Description description, Scope scope,
Order order) {
return new Statement() {
@@ -338,7 +289,7 @@
mState.enterTestMethod(description);
}
- final var classDescription = mState.getClassDescription();
+ final var classDescription = getDescription();
// Class-level annotations are checked by the runner already, so we only check
// method-level annotations here.
@@ -360,7 +311,7 @@
private boolean onAfter(Description description, Scope scope, Order order, Throwable th) {
Log.v(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);
- final var classDescription = mState.getClassDescription();
+ final var classDescription = getDescription();
if (scope == Scope.Instance && order == Order.Outer) {
// End of a test method.
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java
index ead4a84..ec00e8f 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java
@@ -52,37 +52,65 @@
mRunner = runner;
}
- private Description mClassDescription;
+ /**
+ * The RavenwoodConfig used to configure the current Ravenwood environment.
+ * This can either come from mConfig or mRule.
+ */
+ private RavenwoodConfig mCurrentConfig;
+ /**
+ * The RavenwoodConfig declared in the test class
+ */
+ private RavenwoodConfig mConfig;
+ /**
+ * The RavenwoodRule currently in effect, declared in the test class
+ */
+ private RavenwoodRule mRule;
+ private boolean mHasRavenwoodRule;
private Description mMethodDescription;
- private RavenwoodConfig mCurrentConfig;
- private RavenwoodRule mCurrentRule;
- private boolean mHasRavenwoodRule;
-
- public Description getClassDescription() {
- return mClassDescription;
+ public RavenwoodConfig getConfig() {
+ return mCurrentConfig;
}
- public void enterTestClass(Description classDescription) {
- Log.i(TAG, "enterTestClass: description=" + classDescription);
- mClassDescription = classDescription;
+ public void enterTestRunner() {
+ Log.i(TAG, "enterTestRunner: " + mRunner);
- mHasRavenwoodRule = hasRavenwoodRule(mRunner.getTestClass().getJavaClass());
- mCurrentConfig = extractConfiguration(mRunner.getTestClass().getJavaClass());
+ mHasRavenwoodRule = hasRavenwoodRule(mRunner.mTestJavaClass);
+ mConfig = extractConfiguration(mRunner.mTestJavaClass);
+
+ if (mConfig != null) {
+ if (mHasRavenwoodRule) {
+ fail("RavenwoodConfig and RavenwoodRule cannot be used in the same class."
+ + " Suggest migrating to RavenwoodConfig.");
+ }
+ mCurrentConfig = mConfig;
+ } else if (!mHasRavenwoodRule) {
+ // If no RavenwoodConfig and no RavenwoodRule, use a default config
+ mCurrentConfig = new RavenwoodConfig.Builder().build();
+ }
if (mCurrentConfig != null) {
- RavenwoodRuntimeEnvironmentController.init(mCurrentConfig);
+ RavenwoodRuntimeEnvironmentController.init(mRunner);
+ }
+ }
+
+ public void enterTestClass() {
+ Log.i(TAG, "enterTestClass: " + mRunner.mTestJavaClass.getName());
+
+ if (mCurrentConfig != null) {
+ RavenwoodRuntimeEnvironmentController.init(mRunner);
}
}
public void exitTestClass() {
- Log.i(TAG, "exitTestClass: description=" + mClassDescription);
- if (mCurrentConfig != null) {
- try {
+ Log.i(TAG, "exitTestClass: " + mRunner.mTestJavaClass.getName());
+ try {
+ if (mCurrentConfig != null) {
RavenwoodRuntimeEnvironmentController.reset();
- } finally {
- mClassDescription = null;
}
+ } finally {
+ mConfig = null;
+ mRule = null;
}
}
@@ -92,6 +120,7 @@
public void exitTestMethod() {
mMethodDescription = null;
+ RavenwoodRuntimeEnvironmentController.reinit();
}
public void enterRavenwoodRule(RavenwoodRule rule) {
@@ -99,48 +128,32 @@
fail("If you have a RavenwoodRule in your test, make sure the field type is"
+ " RavenwoodRule so Ravenwood can detect it.");
}
- if (mCurrentConfig != null) {
- fail("RavenwoodConfig and RavenwoodRule cannot be used in the same class."
- + " Suggest migrating to RavenwoodConfig.");
- }
- if (mCurrentRule != null) {
+ if (mRule != null) {
fail("Multiple nesting RavenwoodRule's are detected in the same class,"
+ " which is not supported.");
}
- mCurrentRule = rule;
- RavenwoodRuntimeEnvironmentController.init(rule.getConfiguration());
+ mRule = rule;
+ if (mCurrentConfig == null) {
+ mCurrentConfig = rule.getConfiguration();
+ }
+ RavenwoodRuntimeEnvironmentController.init(mRunner);
}
public void exitRavenwoodRule(RavenwoodRule rule) {
- if (mCurrentRule != rule) {
- return; // This happens if the rule did _not_ take effect somehow.
+ if (mRule != rule) {
+ fail("RavenwoodRule did not take effect.");
}
-
- try {
- RavenwoodRuntimeEnvironmentController.reset();
- } finally {
- mCurrentRule = null;
- }
+ mRule = null;
}
/**
* @return a configuration from a test class, if any.
*/
@Nullable
- private RavenwoodConfig extractConfiguration(Class<?> testClass) {
+ private static RavenwoodConfig extractConfiguration(Class<?> testClass) {
var field = findConfigurationField(testClass);
if (field == null) {
- if (mHasRavenwoodRule) {
- // Should be handled by RavenwoodRule
- return null;
- }
-
- // If no RavenwoodConfig and no RavenwoodRule, return a default config
- return new RavenwoodConfig.Builder().build();
- }
- if (mHasRavenwoodRule) {
- fail("RavenwoodConfig and RavenwoodRule cannot be used in the same class."
- + " Suggest migrating to RavenwoodConfig.");
+ return null;
}
try {
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
index de4357c..9002e40 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
@@ -137,7 +137,7 @@
return res;
}
- private static RavenwoodConfig sConfig;
+ private static RavenwoodAwareTestRunner sRunner;
private static RavenwoodSystemProperties sProps;
private static boolean sInitialized = false;
@@ -171,6 +171,10 @@
// Redirect stdout/stdin to liblog.
RuntimeInit.redirectLogStreams();
+ // Touch some references early to ensure they're <clinit>'ed
+ Objects.requireNonNull(Build.TYPE);
+ Objects.requireNonNull(Build.VERSION.SDK);
+
if (RAVENWOOD_VERBOSE_LOGGING) {
RavenwoodCommonUtils.log(TAG, "Force enabling verbose logging");
try {
@@ -191,12 +195,19 @@
/**
* Initialize the environment.
*/
- public static void init(RavenwoodConfig config) {
+ public static void init(RavenwoodAwareTestRunner runner) {
if (RAVENWOOD_VERBOSE_LOGGING) {
- Log.i(TAG, "init() called here", new RuntimeException("STACKTRACE"));
+ Log.i(TAG, "init() called here: " + runner, new RuntimeException("STACKTRACE"));
}
+ if (sRunner == runner) {
+ return;
+ }
+ if (sRunner != null) {
+ reset();
+ }
+ sRunner = runner;
try {
- initInner(config);
+ initInner(runner.mState.getConfig());
} catch (Exception th) {
Log.e(TAG, "init() failed", th);
reset();
@@ -205,10 +216,6 @@
}
private static void initInner(RavenwoodConfig config) throws IOException {
- if (sConfig != null) {
- throw new RavenwoodRuntimeException("Internal error: init() called without reset()");
- }
- sConfig = config;
if (ENABLE_UNCAUGHT_EXCEPTION_DETECTION) {
maybeThrowPendingUncaughtException(false);
Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
@@ -216,7 +223,7 @@
android.os.Process.init$ravenwood(config.mUid, config.mPid);
sOriginalIdentityToken = Binder.clearCallingIdentity();
- Binder.restoreCallingIdentity(packBinderIdentityToken(false, config.mUid, config.mPid));
+ reinit();
setSystemProperties(config.mSystemProperties);
ServiceManager.init$ravenwood();
@@ -269,9 +276,7 @@
config.mInstContext = instContext;
config.mTargetContext = targetContext;
- final Supplier<Resources> systemResourcesLoader = () -> {
- return config.mState.loadResources(null);
- };
+ final Supplier<Resources> systemResourcesLoader = () -> config.mState.loadResources(null);
config.mState.mSystemServerContext =
new RavenwoodContext(ANDROID_PACKAGE_NAME, main, systemResourcesLoader);
@@ -288,10 +293,14 @@
RavenwoodRuntimeEnvironmentController::dumpStacks,
TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
}
+ }
- // Touch some references early to ensure they're <clinit>'ed
- Objects.requireNonNull(Build.TYPE);
- Objects.requireNonNull(Build.VERSION.SDK);
+ /**
+ * Partially re-initialize after each test method invocation
+ */
+ public static void reinit() {
+ var config = sRunner.mState.getConfig();
+ Binder.restoreCallingIdentity(packBinderIdentityToken(false, config.mUid, config.mPid));
}
/**
@@ -301,11 +310,11 @@
if (RAVENWOOD_VERBOSE_LOGGING) {
Log.i(TAG, "reset() called here", new RuntimeException("STACKTRACE"));
}
- if (sConfig == null) {
+ if (sRunner == null) {
throw new RavenwoodRuntimeException("Internal error: reset() already called");
}
- var config = sConfig;
- sConfig = null;
+ var config = sRunner.mState.getConfig();
+ sRunner = null;
if (ENABLE_TIMEOUT_STACKS) {
sPendingTimeout.cancel(false);
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerBase.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerBase.java
index 7c72f6b..31a1416 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerBase.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerBase.java
@@ -74,7 +74,7 @@
}
@Override
- public Description getDescription() {
+ public final Description getDescription() {
return getRealRunner().getDescription();
}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
index 773dba1..3d6ac0f 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
@@ -24,6 +24,8 @@
import android.content.Context;
import android.platform.test.annotations.DisabledOnRavenwood;
+import androidx.test.platform.app.InstrumentationRegistry;
+
import com.android.ravenwood.common.RavenwoodCommonUtils;
import org.junit.rules.TestRule;
@@ -219,8 +221,7 @@
*/
@Deprecated
public Context getContext() {
- return Objects.requireNonNull(mConfiguration.mInstContext,
- "Context is only available during @Test execution");
+ return InstrumentationRegistry.getInstrumentation().getContext();
}
/**
@@ -230,8 +231,7 @@
*/
@Deprecated
public Instrumentation getInstrumentation() {
- return Objects.requireNonNull(mConfiguration.mInstrumentation,
- "Instrumentation is only available during @Test execution");
+ return InstrumentationRegistry.getInstrumentation();
}
@Override
diff --git a/ravenwood/scripts/update-test-mapping.sh b/ravenwood/scripts/update-test-mapping.sh
index e478b50..ab37baf 100755
--- a/ravenwood/scripts/update-test-mapping.sh
+++ b/ravenwood/scripts/update-test-mapping.sh
@@ -23,6 +23,14 @@
# Tests that shouldn't be in presubmit.
EXEMPT='^(SystemUiRavenTests)$'
+is_car() {
+ local module="$1"
+
+ # If the module name starts with "Car", then it's a test for "Car".
+ [[ "$module" =~ ^Car ]]
+ return $?
+}
+
main() {
local script_name="${0##*/}"
local script_dir="${0%/*}"
@@ -62,6 +70,10 @@
fi
echo " {"
echo " \"name\": \"${tests[$i]}\","
+ if is_car "${tests[$i]}"; then
+ echo ' "keywords": ["automotive_code_coverage"],'
+ fi
+
echo " \"host\": true"
echo " }$comma"
diff --git a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodAwareTestRunnerTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodAwareTestRunnerTest.java
index 637f069..4e21f86 100644
--- a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodAwareTestRunnerTest.java
+++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodAwareTestRunnerTest.java
@@ -16,12 +16,15 @@
package com.android.ravenwoodtest.bivalenttest.ravenizer;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.RavenwoodTestRunnerInitializing;
import android.platform.test.ravenwood.RavenwoodRule;
import android.util.Log;
+import androidx.test.platform.app.InstrumentationRegistry;
+
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
@@ -30,6 +33,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.List;
+
/**
* Make sure RavenwoodAwareTestRunnerTest properly delegates to the original runner,
* and also run the special annotated methods.
@@ -61,13 +66,22 @@
sCallTracker.incrementMethodCallCount();
}
+ public RavenwoodAwareTestRunnerTest() {
+ // Make sure the environment is already initialized when the constructor is called
+ assertNotNull(InstrumentationRegistry.getInstrumentation());
+ }
+
@Test
public void test1() {
sCallTracker.incrementMethodCallCount();
}
+ public static List<String> testParams() {
+ return List.of("foo", "bar");
+ }
+
@Test
- @Parameters({"foo", "bar"})
+ @Parameters(method = "testParams")
public void testWithParams(String arg) {
sCallTracker.incrementMethodCallCount();
}
diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerCallbackTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerCallbackTest.java
index bd01313..6720e45 100644
--- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerCallbackTest.java
+++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerCallbackTest.java
@@ -337,9 +337,9 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: Constructor(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$ExceptionFromInnerRunnerConstructorTest)
- testFailure: Exception detected in constructor
- testFinished: Constructor(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$ExceptionFromInnerRunnerConstructorTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$ExceptionFromInnerRunnerConstructorTest)
+ testFailure: Failed to instantiate class androidx.test.ext.junit.runners.AndroidJUnit4
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$ExceptionFromInnerRunnerConstructorTest)
testSuiteFinished: classes
testRunFinished: 1,1,0,0
""")
@@ -439,9 +439,9 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: Constructor(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$BrokenRunnerTest)
- testFailure: Exception detected in constructor
- testFinished: Constructor(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$BrokenRunnerTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$BrokenRunnerTest)
+ testFailure: Failed to instantiate class com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$BrokenTestRunner
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$BrokenRunnerTest)
testSuiteFinished: classes
testRunFinished: 1,1,0,0
""")
diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java
index 73ea64f..02d1073 100644
--- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java
+++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java
@@ -106,17 +106,11 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: testMethod1(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest)
testFailure: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest.sConfig expected to be public static
- testFinished: testMethod1(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest)
- testStarted: testMethod2(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest)
- testFailure: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest.sConfig expected to be public static
- testFinished: testMethod2(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest)
- testStarted: testMethod3(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest)
- testFailure: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest.sConfig expected to be public static
- testFinished: testMethod3(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest)
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ErrorMustBeReportedFromEachTest)
testSuiteFinished: classes
- testRunFinished: 3,3,0,0
+ testRunFinished: 1,1,0,0
""")
// CHECKSTYLE:ON
public static class ErrorMustBeReportedFromEachTest {
@@ -145,9 +139,9 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$DuplicateConfigTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$DuplicateConfigTest)
testFailure: Class com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest.DuplicateConfigTest has multiple fields with @RavenwoodConfig.Config
- testFinished: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$DuplicateConfigTest)
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$DuplicateConfigTest)
testSuiteFinished: classes
testRunFinished: 1,1,0,0
""")
@@ -175,9 +169,9 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonStaticConfigTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonStaticConfigTest)
testFailure: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonStaticConfigTest.sConfig expected to be public static
- testFinished: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonStaticConfigTest)
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonStaticConfigTest)
testSuiteFinished: classes
testRunFinished: 1,1,0,0
""")
@@ -201,9 +195,9 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonPublicConfigTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonPublicConfigTest)
testFailure: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonPublicConfigTest.sConfig expected to be public static
- testFinished: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonPublicConfigTest)
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$NonPublicConfigTest)
testSuiteFinished: classes
testRunFinished: 1,1,0,0
""")
@@ -227,9 +221,9 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeConfigTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeConfigTest)
testFailure: Field com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest.WrongTypeConfigTest.sConfig has @RavenwoodConfig.Config but type is not RavenwoodConfig
- testFinished: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeConfigTest)
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeConfigTest)
testSuiteFinished: classes
testRunFinished: 1,1,0,0
""")
@@ -282,9 +276,9 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithInstanceRuleTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithInstanceRuleTest)
testFailure: RavenwoodConfig and RavenwoodRule cannot be used in the same class. Suggest migrating to RavenwoodConfig.
- testFinished: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithInstanceRuleTest)
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithInstanceRuleTest)
testSuiteFinished: classes
testRunFinished: 1,1,0,0
""")
@@ -311,9 +305,9 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: Constructor(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithStaticRuleTest)
- testFailure: Exception detected in constructor
- testFinished: Constructor(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithStaticRuleTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithStaticRuleTest)
+ testFailure: Failed to instantiate class androidx.test.ext.junit.runners.AndroidJUnit4
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithStaticRuleTest)
testSuiteFinished: classes
testRunFinished: 1,1,0,0
""")
@@ -400,9 +394,9 @@
@Expected("""
testRunStarted: classes
testSuiteStarted: classes
- testStarted: test(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleInBaseClassTest)
+ testStarted: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleInBaseClassTest)
testFailure: RavenwoodConfig and RavenwoodRule cannot be used in the same class. Suggest migrating to RavenwoodConfig.
- testFinished: test(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleInBaseClassTest)
+ testFinished: initializationError(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleInBaseClassTest)
testSuiteFinished: classes
testRunFinished: 1,1,0,0
""")
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 51c768b..dc7749c 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -48,6 +48,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.net.vcn.Flags;
import android.net.vcn.IVcnManagementService;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
@@ -878,6 +879,7 @@
private void garbageCollectAndWriteVcnConfigsLocked() {
final SubscriptionManager subMgr = mContext.getSystemService(SubscriptionManager.class);
+ final Set<ParcelUuid> subGroups = mLastSnapshot.getAllSubscriptionGroups();
boolean shouldWrite = false;
@@ -885,11 +887,20 @@
while (configsIterator.hasNext()) {
final ParcelUuid subGrp = configsIterator.next();
- final List<SubscriptionInfo> subscriptions = subMgr.getSubscriptionsInGroup(subGrp);
- if (subscriptions == null || subscriptions.isEmpty()) {
- // Trim subGrps with no more subscriptions; must have moved to another subGrp
- configsIterator.remove();
- shouldWrite = true;
+ if (Flags.fixConfigGarbageCollection()) {
+ if (!subGroups.contains(subGrp)) {
+ // Trim subGrps with no more subscriptions; must have moved to another subGrp
+ logDbg("Garbage collect VcnConfig for group=" + subGrp);
+ configsIterator.remove();
+ shouldWrite = true;
+ }
+ } else {
+ final List<SubscriptionInfo> subscriptions = subMgr.getSubscriptionsInGroup(subGrp);
+ if (subscriptions == null || subscriptions.isEmpty()) {
+ // Trim subGrps with no more subscriptions; must have moved to another subGrp
+ configsIterator.remove();
+ shouldWrite = true;
+ }
}
}
@@ -1094,13 +1105,7 @@
synchronized (mLock) {
final Vcn vcn = mVcns.get(subGrp);
final VcnConfig vcnConfig = mConfigs.get(subGrp);
- if (vcn != null) {
- if (vcnConfig == null) {
- // TODO: b/284381334 Investigate for the root cause of this issue
- // and handle it properly
- logWtf("Vcn instance exists but VcnConfig does not for " + subGrp);
- }
-
+ if (vcn != null && vcnConfig != null) {
if (vcn.getStatus() == VCN_STATUS_CODE_ACTIVE) {
isVcnManagedNetwork = true;
}
@@ -1120,6 +1125,8 @@
}
}
}
+ } else if (vcn != null && vcnConfig == null) {
+ logWtf("Vcn instance exists but VcnConfig does not for " + subGrp);
}
}
diff --git a/services/core/java/com/android/server/integrity/parser/LimitInputStream.java b/services/core/java/com/android/server/integrity/parser/LimitInputStream.java
deleted file mode 100644
index a91bbb7..0000000
--- a/services/core/java/com/android/server/integrity/parser/LimitInputStream.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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 com.android.server.integrity.parser;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/** An {@link InputStream} that basically truncates another {@link InputStream} */
-public class LimitInputStream extends FilterInputStream {
- private int mReadBytes;
- private final int mLimit;
-
- public LimitInputStream(InputStream in, int limit) {
- super(in);
- if (limit < 0) {
- throw new IllegalArgumentException("limit " + limit + " cannot be negative");
- }
- mReadBytes = 0;
- mLimit = limit;
- }
-
- @Override
- public int available() throws IOException {
- return Math.min(super.available(), mLimit - mReadBytes);
- }
-
- @Override
- public int read() throws IOException {
- if (mReadBytes == mLimit) {
- return -1;
- }
- mReadBytes++;
- return super.read();
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- if (len <= 0) {
- return 0;
- }
- int available = available();
- if (available <= 0) {
- return -1;
- }
- int result = super.read(b, off, Math.min(len, available));
- mReadBytes += result;
- return result;
- }
-
- @Override
- public long skip(long n) throws IOException {
- if (n <= 0) {
- return 0;
- }
- int available = available();
- if (available <= 0) {
- return 0;
- }
- int bytesToSkip = (int) Math.min(available, n);
- long bytesSkipped = super.skip(bytesToSkip);
- mReadBytes += (int) bytesSkipped;
- return bytesSkipped;
- }
-}
diff --git a/services/core/java/com/android/server/integrity/parser/RandomAccessInputStream.java b/services/core/java/com/android/server/integrity/parser/RandomAccessInputStream.java
deleted file mode 100644
index 206e6a1..0000000
--- a/services/core/java/com/android/server/integrity/parser/RandomAccessInputStream.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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 com.android.server.integrity.parser;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/** A wrapper around {@link RandomAccessObject} to turn it into a {@link InputStream}. */
-public class RandomAccessInputStream extends InputStream {
-
- private final RandomAccessObject mRandomAccessObject;
-
- private int mPosition;
-
- public RandomAccessInputStream(RandomAccessObject object) throws IOException {
- mRandomAccessObject = object;
- mPosition = 0;
- }
-
- /** Returns the position of the file pointer. */
- public int getPosition() {
- return mPosition;
- }
-
- /** See {@link RandomAccessObject#seek(int)} */
- public void seek(int position) throws IOException {
- mRandomAccessObject.seek(position);
- mPosition = position;
- }
-
- @Override
- public int available() throws IOException {
- return mRandomAccessObject.length() - mPosition;
- }
-
- @Override
- public void close() throws IOException {
- mRandomAccessObject.close();
- }
-
- @Override
- public int read() throws IOException {
- if (available() <= 0) {
- return -1;
- }
- mPosition++;
- return mRandomAccessObject.read();
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- if (len <= 0) {
- return 0;
- }
- int available = available();
- if (available <= 0) {
- return -1;
- }
- int result = mRandomAccessObject.read(b, off, Math.min(len, available));
- mPosition += result;
- return result;
- }
-
- @Override
- public long skip(long n) throws IOException {
- if (n <= 0) {
- return 0;
- }
- int available = available();
- if (available <= 0) {
- return 0;
- }
- int skipAmount = (int) Math.min(available, n);
- mPosition += skipAmount;
- mRandomAccessObject.seek(mPosition);
- return skipAmount;
- }
-}
diff --git a/services/core/java/com/android/server/integrity/parser/RandomAccessObject.java b/services/core/java/com/android/server/integrity/parser/RandomAccessObject.java
deleted file mode 100644
index d9b2e38..0000000
--- a/services/core/java/com/android/server/integrity/parser/RandomAccessObject.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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 com.android.server.integrity.parser;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-
-/** An interface for random access objects like RandomAccessFile or byte arrays. */
-public abstract class RandomAccessObject {
-
- /** See {@link RandomAccessFile#seek(long)}. */
- public abstract void seek(int position) throws IOException;
-
- /** See {@link RandomAccessFile#read()}. */
- public abstract int read() throws IOException;
-
- /** See {@link RandomAccessFile#read(byte[], int, int)}. */
- public abstract int read(byte[] bytes, int off, int len) throws IOException;
-
- /** See {@link RandomAccessFile#close()}. */
- public abstract void close() throws IOException;
-
- /** See {@link java.io.RandomAccessFile#length()}. */
- public abstract int length();
-
- /** Static constructor from a file. */
- public static RandomAccessObject ofFile(File file) throws IOException {
- return new RandomAccessFileObject(file);
- }
-
- /** Static constructor from a byte array. */
- public static RandomAccessObject ofBytes(byte[] bytes) {
- return new RandomAccessByteArrayObject(bytes);
- }
-
- private static class RandomAccessFileObject extends RandomAccessObject {
- private final RandomAccessFile mRandomAccessFile;
- // We cache the length since File.length() invokes file IO.
- private final int mLength;
-
- RandomAccessFileObject(File file) throws IOException {
- long length = file.length();
- if (length > Integer.MAX_VALUE) {
- throw new IOException("Unsupported file size (too big) " + length);
- }
-
- mRandomAccessFile = new RandomAccessFile(file, /* mode= */ "r");
- mLength = (int) length;
- }
-
- @Override
- public void seek(int position) throws IOException {
- mRandomAccessFile.seek(position);
- }
-
- @Override
- public int read() throws IOException {
- return mRandomAccessFile.read();
- }
-
- @Override
- public int read(byte[] bytes, int off, int len) throws IOException {
- return mRandomAccessFile.read(bytes, off, len);
- }
-
- @Override
- public void close() throws IOException {
- mRandomAccessFile.close();
- }
-
- @Override
- public int length() {
- return mLength;
- }
- }
-
- private static class RandomAccessByteArrayObject extends RandomAccessObject {
-
- private final ByteBuffer mBytes;
-
- RandomAccessByteArrayObject(byte[] bytes) {
- mBytes = ByteBuffer.wrap(bytes);
- }
-
- @Override
- public void seek(int position) throws IOException {
- mBytes.position(position);
- }
-
- @Override
- public int read() throws IOException {
- if (!mBytes.hasRemaining()) {
- return -1;
- }
-
- return mBytes.get() & 0xFF;
- }
-
- @Override
- public int read(byte[] bytes, int off, int len) throws IOException {
- int bytesToCopy = Math.min(len, mBytes.remaining());
- if (bytesToCopy <= 0) {
- return 0;
- }
- mBytes.get(bytes, off, len);
- return bytesToCopy;
- }
-
- @Override
- public void close() throws IOException {}
-
- @Override
- public int length() {
- return mBytes.capacity();
- }
- }
-}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index bbdac56..8798a64 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1183,9 +1183,7 @@
// If config_disableWeaverOnUnsecuredUsers=true, then the Weaver HAL may be buggy and
// need multiple retries before it works here to unwrap the SP, if the SP was already
- // protected by Weaver. Note that the problematic HAL can also deadlock if called with
- // the ActivityManagerService lock held, but that should not be a problem here since
- // that lock isn't held here, unlike unlockUserKeyIfUnsecured() where it is.
+ // protected by Weaver.
for (int i = 0; i < 12 && sp == null; i++) {
Slog.e(TAG, "Failed to unwrap synthetic password. Waiting 5 seconds to retry.");
SystemClock.sleep(5000);
diff --git a/services/core/java/com/android/server/vcn/OWNERS b/services/core/java/com/android/server/vcn/OWNERS
index 2441e77..937699a 100644
--- a/services/core/java/com/android/server/vcn/OWNERS
+++ b/services/core/java/com/android/server/vcn/OWNERS
@@ -1,7 +1,6 @@
set noparent
-benedictwong@google.com
-ckesting@google.com
evitayan@google.com
-junyin@google.com
nharold@google.com
+benedictwong@google.com #{LAST_RESORT_SUGGESTION}
+yangji@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index baf84cf..3392d03 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -436,6 +436,17 @@
return mPrivilegedPackages.keySet();
}
+ /** Returns all subscription groups */
+ @NonNull
+ public Set<ParcelUuid> getAllSubscriptionGroups() {
+ final Set<ParcelUuid> subGroups = new ArraySet<>();
+ for (SubscriptionInfo subInfo : mSubIdToInfoMap.values()) {
+ subGroups.add(subInfo.getGroupUuid());
+ }
+
+ return subGroups;
+ }
+
/** Checks if the provided package is carrier privileged for the specified sub group. */
public boolean packageHasPermissionsForSubscriptionGroup(
@NonNull ParcelUuid subGrp, @NonNull String packageName) {
diff --git a/tests/vcn/OWNERS b/tests/vcn/OWNERS
index 2441e77..937699a 100644
--- a/tests/vcn/OWNERS
+++ b/tests/vcn/OWNERS
@@ -1,7 +1,6 @@
set noparent
-benedictwong@google.com
-ckesting@google.com
evitayan@google.com
-junyin@google.com
nharold@google.com
+benedictwong@google.com #{LAST_RESORT_SUGGESTION}
+yangji@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 7e0bbc4..3828a71 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -70,6 +70,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.Uri;
+import android.net.vcn.Flags;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
@@ -84,6 +85,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.os.test.TestLooper;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -102,6 +104,7 @@
import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -119,6 +122,8 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnManagementServiceTest {
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private static final String CONTEXT_ATTRIBUTION_TAG = "VCN";
private static final String TEST_PACKAGE_NAME =
VcnManagementServiceTest.class.getPackage().getName();
@@ -288,6 +293,8 @@
doReturn(Collections.singleton(TRANSPORT_WIFI))
.when(mMockDeps)
.getRestrictedTransports(any(), any(), any());
+
+ mSetFlagsRule.enableFlags(Flags.FLAG_FIX_CONFIG_GARBAGE_COLLECTION);
}
@@ -438,6 +445,14 @@
return subIds;
}).when(snapshot).getAllSubIdsInGroup(any());
+ doAnswer(invocation -> {
+ final Set<ParcelUuid> subGroups = new ArraySet<>();
+ for (Entry<Integer, ParcelUuid> entry : subIdToGroupMap.entrySet()) {
+ subGroups.add(entry.getValue());
+ }
+ return subGroups;
+ }).when(snapshot).getAllSubscriptionGroups();
+
return snapshot;
}
@@ -1483,6 +1498,28 @@
}
@Test
+ public void testGarbageCollectionKeepConfigUntilNewSnapshot() throws Exception {
+ setupActiveSubscription(TEST_UUID_2);
+ startAndGetVcnInstance(TEST_UUID_2);
+
+ // Report loss of subscription from mSubMgr
+ doReturn(Collections.emptyList()).when(mSubMgr).getSubscriptionsInGroup(any());
+ triggerSubscriptionTrackerCbAndGetSnapshot(
+ TEST_UUID_2,
+ Collections.singleton(TEST_UUID_2),
+ Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_2));
+
+ assertTrue(mVcnMgmtSvc.getConfigs().containsKey(TEST_UUID_2));
+
+ // Report loss of subscription from snapshot
+ triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet());
+
+ mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
+ mTestLooper.dispatchAll();
+ assertFalse(mVcnMgmtSvc.getConfigs().containsKey(TEST_UUID_2));
+ }
+
+ @Test
public void testVcnCarrierConfigChangeUpdatesPolicyListener() throws Exception {
setupActiveSubscription(TEST_UUID_2);