/*
 * 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.os;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;

import dalvik.system.VMRuntime;

import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.DirectByteBuffer;
import java.nio.NioUtils;

import sun.misc.Cleaner;

/**
 * SharedMemory enables the creation, mapping, and protection control over anonymous shared memory.
 */
public final class SharedMemory implements Parcelable, Closeable {

    private final FileDescriptor mFileDescriptor;
    private final int mSize;
    private final MemoryRegistration mMemoryRegistration;
    private Cleaner mCleaner;

    private SharedMemory(FileDescriptor fd) {
        // This constructor is only used internally so it should be impossible to hit any of the
        // exceptions unless something goes horribly wrong.
        if (fd == null) {
            throw new IllegalArgumentException(
                    "Unable to create SharedMemory from a null FileDescriptor");
        }
        if (!fd.valid()) {
            throw new IllegalArgumentException(
                    "Unable to create SharedMemory from closed FileDescriptor");
        }
        mFileDescriptor = fd;
        mSize = nGetSize(mFileDescriptor);
        if (mSize <= 0) {
            throw new IllegalArgumentException("FileDescriptor is not a valid ashmem fd");
        }

        mMemoryRegistration = new MemoryRegistration(mSize);
        mCleaner = Cleaner.create(mFileDescriptor,
                new Closer(mFileDescriptor, mMemoryRegistration));
    }

    /**
     * Creates an anonymous SharedMemory instance with the provided debug name and size. The name
     * is only used for debugging purposes and can help identify what the shared memory is used
     * for when inspecting memory maps for the processes that have mapped this SharedMemory
     * instance.
     *
     * @param name The debug name to use for this SharedMemory instance. This can be null, however
     *             a debug name is recommended to help identify memory usage when using tools
     *             such as lsof or examining /proc/[pid]/maps
     * @param size The size of the shared memory to create. Must be greater than 0.
     * @return A SharedMemory instance of the requested size
     * @throws ErrnoException if the requested allocation fails.
     */
    public static @NonNull SharedMemory create(@Nullable String name, int size)
            throws ErrnoException {
        if (size <= 0) {
            throw new IllegalArgumentException("Size must be greater than zero");
        }
        return new SharedMemory(nCreate(name, size));
    }

    private void checkOpen() {
        if (!mFileDescriptor.valid()) {
            throw new IllegalStateException("SharedMemory is closed");
        }
    }

    private static final int PROT_MASK = OsConstants.PROT_READ | OsConstants.PROT_WRITE
            | OsConstants.PROT_EXEC | OsConstants.PROT_NONE;

    private static void validateProt(int prot) {
        if ((prot & ~PROT_MASK) != 0) {
            throw new IllegalArgumentException("Invalid prot value");
        }
    }

    /**
     * Sets the protection on the shared memory to the combination specified in prot, which
     * is either a bitwise-or'd combination of {@link android.system.OsConstants#PROT_READ},
     * {@link android.system.OsConstants#PROT_WRITE}, {@link android.system.OsConstants#PROT_EXEC}
     * from {@link android.system.OsConstants}, or {@link android.system.OsConstants#PROT_NONE},
     * to remove all further access.
     *
     * Note that protection can only ever be removed, not added. By default shared memory
     * is created with protection set to PROT_READ | PROT_WRITE | PROT_EXEC. The protection
     * passed here also only applies to any mappings created after calling this method. Existing
     * mmaps of the shared memory retain whatever protection they had when they were created.
     *
     * A common usage of this is to share a read-only copy of the data with something else. To do
     * that first create the read/write mapping with PROT_READ | PROT_WRITE,
     * then call setProtect(PROT_READ) to remove write capability, then send the SharedMemory
     * to another process. That process will only be able to mmap with PROT_READ.
     *
     * @param prot Any bitwise-or'ed combination of
     *                  {@link android.system.OsConstants#PROT_READ},
     *                  {@link android.system.OsConstants#PROT_WRITE}, and
     *                  {@link android.system.OsConstants#PROT_EXEC}; or
     *                  {@link android.system.OsConstants#PROT_NONE}
     * @return Whether or not the requested protection was applied. Returns true on success,
     * false if the requested protection was broader than the existing protection.
     */
    public boolean setProtect(int prot) {
        checkOpen();
        validateProt(prot);
        int errno = nSetProt(mFileDescriptor, prot);
        return errno == 0;
    }

    /**
     * Returns the backing {@link FileDescriptor} for this SharedMemory object. The SharedMemory
     * instance retains ownership of the FileDescriptor.
     *
     * This FileDescriptor is interoperable with the ASharedMemory NDK APIs.
     *
     * @return Returns the FileDescriptor associated with this object.
     *
     * @hide Exists only for MemoryFile interop
     */
    public @NonNull FileDescriptor getFileDescriptor() {
        return mFileDescriptor;
    }

    /**
     * Returns the backing native fd int for this SharedMemory object. The SharedMemory
     * instance retains ownership of the fd.
     *
     * This fd is interoperable with the ASharedMemory NDK APIs.
     *
     * @return Returns the native fd associated with this object, or -1 if it is already closed.
     *
     * @hide Exposed for native ASharedMemory_dupFromJava()
     */
    @UnsupportedAppUsage
    public int getFd() {
        return mFileDescriptor.getInt$();
    }

    /**
     * @return The size of the SharedMemory region.
     */
    public int getSize() {
        checkOpen();
        return mSize;
    }

    /**
     * Creates a read/write mapping of the entire shared memory region. This requires the the
     * protection level of the shared memory is at least PROT_READ|PROT_WRITE or the map will fail.
     *
     * Use {@link #map(int, int, int)} to have more control over the mapping if desired.
     * This is equivalent to map(OsConstants.PROT_READ | OsConstants.PROT_WRITE, 0, getSize())
     *
     * @return A ByteBuffer mapping
     * @throws ErrnoException if the mmap call failed.
     */
    public @NonNull ByteBuffer mapReadWrite() throws ErrnoException {
        return map(OsConstants.PROT_READ | OsConstants.PROT_WRITE, 0, mSize);
    }

    /**
     * Creates a read-only mapping of the entire shared memory region. This requires the the
     * protection level of the shared memory is at least PROT_READ or the map will fail.
     *
     * Use {@link #map(int, int, int)} to have more control over the mapping if desired.
     * This is equivalent to map(OsConstants.PROT_READ, 0, getSize())
     *
     * @return A ByteBuffer mapping
     * @throws ErrnoException if the mmap call failed.
     */
    public @NonNull ByteBuffer mapReadOnly() throws ErrnoException {
        return map(OsConstants.PROT_READ, 0, mSize);
    }

    /**
     * Creates an mmap of the SharedMemory with the specified prot, offset, and length. This will
     * always produce a new ByteBuffer window to the backing shared memory region. Every call
     * to map() may be paired with a call to {@link #unmap(ByteBuffer)} when the ByteBuffer
     * returned by map() is no longer needed.
     *
     * @param prot A bitwise-or'd combination of PROT_READ, PROT_WRITE, PROT_EXEC, or PROT_NONE.
     * @param offset The offset into the shared memory to begin mapping. Must be >= 0 and less than
     *         getSize().
     * @param length The length of the region to map. Must be > 0 and offset + length must not
     *         exceed getSize().
     * @return A ByteBuffer mapping.
     * @throws ErrnoException if the mmap call failed.
     */
    public @NonNull ByteBuffer map(int prot, int offset, int length) throws ErrnoException {
        checkOpen();
        validateProt(prot);
        if (offset < 0) {
            throw new IllegalArgumentException("Offset must be >= 0");
        }
        if (length <= 0) {
            throw new IllegalArgumentException("Length must be > 0");
        }
        if (offset + length > mSize) {
            throw new IllegalArgumentException("offset + length must not exceed getSize()");
        }
        long address = Os.mmap(0, length, prot, OsConstants.MAP_SHARED, mFileDescriptor, offset);
        boolean readOnly = (prot & OsConstants.PROT_WRITE) == 0;
        Runnable unmapper = new Unmapper(address, length, mMemoryRegistration.acquire());
        return new DirectByteBuffer(length, address, mFileDescriptor, unmapper, readOnly);
    }

    /**
     * Unmaps a buffer previously returned by {@link #map(int, int, int)}. This will immediately
     * release the backing memory of the ByteBuffer, invalidating all references to it. Only
     * call this method if there are no duplicates of the ByteBuffer in use and don't
     * access the ByteBuffer after calling this method.
     *
     * @param buffer The buffer to unmap
     */
    public static void unmap(@NonNull ByteBuffer buffer) {
        if (buffer instanceof DirectByteBuffer) {
            NioUtils.freeDirectBuffer(buffer);
        } else {
            throw new IllegalArgumentException(
                    "ByteBuffer wasn't created by #map(int, int, int); can't unmap");
        }
    }

    /**
     * Close the backing {@link FileDescriptor} of this SharedMemory instance. Note that all
     * open mappings of the shared memory will remain valid and may continue to be used. The
     * shared memory will not be freed until all file descriptor handles are closed and all
     * memory mappings are unmapped.
     */
    @Override
    public void close() {
        if (mCleaner != null) {
            mCleaner.clean();
            mCleaner = null;
        }
    }

    @Override
    public int describeContents() {
        return CONTENTS_FILE_DESCRIPTOR;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        checkOpen();
        dest.writeFileDescriptor(mFileDescriptor);
    }

    /**
     * Returns a dup'd ParcelFileDescriptor from the SharedMemory FileDescriptor.
     * This obeys standard POSIX semantics, where the
     * new file descriptor shared state such as file position with the
     * original file descriptor.
     * TODO: propose this method as a public or system API for next release to achieve parity with
     *  NDK ASharedMemory_dupFromJava.
     *
     * @hide
     */
    public ParcelFileDescriptor getFdDup() throws IOException {
        return ParcelFileDescriptor.dup(mFileDescriptor);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<SharedMemory> CREATOR =
            new Parcelable.Creator<SharedMemory>() {
        @Override
        public SharedMemory createFromParcel(Parcel source) {
            FileDescriptor descriptor = source.readRawFileDescriptor();
            return new SharedMemory(descriptor);
        }

        @Override
        public SharedMemory[] newArray(int size) {
            return new SharedMemory[size];
        }
    };

    /**
     * Cleaner that closes the FD
     */
    private static final class Closer implements Runnable {
        private FileDescriptor mFd;
        private MemoryRegistration mMemoryReference;

        private Closer(FileDescriptor fd, MemoryRegistration memoryReference) {
            mFd = fd;
            mMemoryReference = memoryReference;
        }

        @Override
        public void run() {
            try {
                Os.close(mFd);
            } catch (ErrnoException e) { /* swallow error */ }
            mMemoryReference.release();
            mMemoryReference = null;
        }
    }

    /**
     * Cleaner that munmap regions
     */
    private static final class Unmapper implements Runnable {
        private long mAddress;
        private int mSize;
        private MemoryRegistration mMemoryReference;

        private Unmapper(long address, int size, MemoryRegistration memoryReference) {
            mAddress = address;
            mSize = size;
            mMemoryReference = memoryReference;
        }

        @Override
        public void run() {
            try {
                Os.munmap(mAddress, mSize);
            } catch (ErrnoException e) { /* swallow exception */ }
            mMemoryReference.release();
            mMemoryReference = null;
        }
    }

    /**
     * Helper class that ensures that the native allocation pressure against the VM heap stays
     * active until the FD is closed as well as all mappings from that FD are closed.
     */
    private static final class MemoryRegistration {
        private int mSize;
        private int mReferenceCount;

        private MemoryRegistration(int size) {
            mSize = size;
            mReferenceCount = 1;
            VMRuntime.getRuntime().registerNativeAllocation(mSize);
        }

        public synchronized MemoryRegistration acquire() {
            mReferenceCount++;
            return this;
        }

        public synchronized void release() {
            mReferenceCount--;
            if (mReferenceCount == 0) {
                VMRuntime.getRuntime().registerNativeFree(mSize);
            }
        }
    }

    private static native FileDescriptor nCreate(String name, int size) throws ErrnoException;
    private static native int nGetSize(FileDescriptor fd);
    private static native int nSetProt(FileDescriptor fd, int prot);
}
