Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb1921d4 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[Ravenwood] Make FileInput/OutputStream behave like libcore" into main

parents cfa65656 0a8f7f56
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -7,7 +7,9 @@
    { "name": "hoststubgen-invoke-test" },
    { "name": "RavenwoodMockitoTest_device" },
    { "name": "RavenwoodBivalentTest_device" },
    { "name": "RavenwoodBivalentTest_device_ravenizer" },

    // Running ravenizer on device side tests is unsupported: b/411506416
    // { "name": "RavenwoodBivalentTest_device_ravenizer" },

    { "name": "RavenwoodBivalentInstTest_nonself_inst" },
    { "name": "RavenwoodBivalentInstTest_self_inst_device" },
+72 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.ravenwood;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * FileInputStream tracking fd ownership, emulating libcore behavior.
 */
public class RavenwoodFileInputStream extends FileInputStream {

    private final boolean mIsFdOwner;

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileInputStream(String name) throws FileNotFoundException {
        super(name);
        mIsFdOwner = true;
    }

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileInputStream(File file) throws FileNotFoundException {
        super(file);
        mIsFdOwner = true;
    }

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileInputStream(FileDescriptor fdObj) {
        this(fdObj, false);
    }

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileInputStream(FileDescriptor fdObj, boolean isFdOwner) {
        super(fdObj);
        this.mIsFdOwner = isFdOwner;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() throws IOException {
        if (mIsFdOwner) {
            // Only close when we are the owner
            super.close();
        }
    }
}
+88 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.ravenwood;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * FileOutputStream tracking fd ownership, emulating libcore behavior.
 */
public class RavenwoodFileOutputStream extends FileOutputStream {

    private final boolean mIsFdOwner;

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileOutputStream(String name) throws FileNotFoundException {
        super(name);
        mIsFdOwner = true;
    }

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileOutputStream(String name, boolean append) throws FileNotFoundException {
        super(name, append);
        mIsFdOwner = true;
    }

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileOutputStream(File file) throws FileNotFoundException {
        super(file);
        mIsFdOwner = true;
    }

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileOutputStream(File file, boolean append) throws FileNotFoundException {
        super(file, append);
        mIsFdOwner = true;
    }

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileOutputStream(FileDescriptor fdObj) {
        this(fdObj, false);
    }

    /**
     * {@inheritDoc}
     */
    public RavenwoodFileOutputStream(FileDescriptor fdObj, boolean isFdOwner) {
        super(fdObj);
        this.mIsFdOwner = isFdOwner;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() throws IOException {
        if (mIsFdOwner) {
            // Only close when we are the owner
            super.close();
        }
    }
}
+125 −0
Original line number Diff line number Diff line
@@ -13,12 +13,14 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.ravenwoodtest.bivalenttest.ravenizer;
package com.android.ravenwoodtest.bivalenttest;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import android.platform.test.ravenwood.RavenwoodRule;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -26,6 +28,9 @@ import android.system.OsConstants;
import org.junit.Test;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.regex.Pattern;

@@ -57,7 +62,64 @@ public class RavenwoodJdkPatchTest {
            Os.close(fd);
            assertEquals(-1, fd.getInt$());
        } finally {
            if (fd.valid()) {
                Os.close(fd);
            }
        }
    }

    private static class SubFileInputStream extends FileInputStream {

        SubFileInputStream(FileDescriptor fdObj) {
            super(fdObj);
        }
    }

    private static class SubFileOutputStream extends FileOutputStream {

        SubFileOutputStream(FileDescriptor fdObj) {
            super(fdObj);
        }
    }

    @Test
    public void testFileInputOutputStream() throws ErrnoException, IOException {
        FileDescriptor fd = Os.open("/dev/urandom", OsConstants.O_RDWR, 0);
        try {
            try (var fis = new FileInputStream(fd)) {
                if (RavenwoodRule.isOnRavenwood()) {
                    assertEquals("com.android.ravenwood.RavenwoodFileInputStream",
                            fis.getClass().getName());
                }
                // It should be the exact same instance, don't use assertEquals here
                assertTrue(fis.getFD() == fd);
            }
            assertTrue(fd.valid());
            try (var fos = new FileOutputStream(fd)) {
                if (RavenwoodRule.isOnRavenwood()) {
                    assertEquals("com.android.ravenwood.RavenwoodFileOutputStream",
                            fos.getClass().getName());
                }
                // It should be the exact same instance, don't use assertEquals here
                assertTrue(fos.getFD() == fd);
            }
            assertTrue(fd.valid());
            new SubFileInputStream(fd).close();
            assertTrue(fd.valid());
            new SubFileOutputStream(fd).close();
            assertTrue(fd.valid());
            new SubFileInputStream(fd) {}.close();
            assertTrue(fd.valid());
            new SubFileOutputStream(fd) {}.close();
        } finally {
            Os.close(fd);
        }

        fd = Os.open("/dev/urandom", OsConstants.O_RDONLY, 0);
        new FileInputStream(fd, true).close();
        assertFalse(fd.valid());

        // For some reason, FileOutputStream(FileDescriptor, boolean) does not exist in any stub
        // JARs during build time. We cannot check whether the constructor patch works in this test.
    }
}
+0 −11
Original line number Diff line number Diff line
@@ -14,14 +14,3 @@ class :sysprops keepclass

# Keep all resource R classes
class :r keepclass

# Support APIs not available in standard JRE
class java.io.FileDescriptor  # no-pta
    method getInt$ @com.android.ravenwood.RavenwoodJdkPatch.getInt$
    method setInt$ @com.android.ravenwood.RavenwoodJdkPatch.setInt$
class java.util.LinkedHashMap  # no-pta
    method eldest @com.android.ravenwood.RavenwoodJdkPatch.eldest

# Always set flag UNICODE_CHARACTER_CLASS when compiling regex
class java.util.regex.Pattern keep
    method compile @com.android.ravenwood.RavenwoodJdkPatch.compilePattern
Loading