Sharing shared file descriptors in an Android application and processes using a middleware

We have two processes that interact through shared memory to read / write data. One of the processes is the application (client), and the other is the background service, which is a separate application in this example, it is the ashmem service manufacturer.

  • AshmemService: - This is a help desk that is sticky, it provides an API for creating a shared memory channel using the android MemoryFile API. This service creates shared memory and receives a file descriptor, and fd is passed to the client process through the middleware interface.

  • AshmemClient: is an application that retrieves a file descriptor for a shared memory channel from AshmemService. This client application communicates with the service, after connecting it, it calls the apl apl interface to get fd. Creating a channel works fine, which creates shared memory. Now for testing purposes, I am writing a block of bytes from Client to shared memory. as soon as it is written, I try to use the same block in the service for valid data received from the application.

In the Client application, when I try to write a block of 128 bytes, the records return 0, so it looks like I can’t write to FD, which is obtained using an arbitrary binder. Even I checked that fd acts through the fd.valid () API.

pfd.getStatSize () returns -1. I think that I am not getting the correct fd from the detailed file descriptor.

http://developer.android.com/reference/android/os/Parcel.html ,

- : fd , , .. , , , , , , , .

    package com.example.service.ashmem;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.util.Log;


public class ConnectionWriter implements Parcelable {
    public final static String TAG = "ConnectionWriter";

    protected FileOutputStream fos = null;
    protected FileDescriptor fd = null;
    protected int noofBlocks = 0;
    protected int blocksize = 0;
    protected int lastPosition;
    protected int chanId;

    public ConnectionWriter(MemoryFileChannel channel, int chanId) {

        this.fd = channel.getFileDescriptor();
        channel.getParcelFileDescriptor();
        this.chanId = chanId;
        this.blocksize = channel.getBlocksize();
        this.noofBlocks = channel.getNoofBlocks();
        Log.d(TAG, "ctor: chanId: " + chanId + " fd valid: " + fd.valid()+ " fd: "+fd);
    }

    public ConnectionWriter(Parcel in) {
        readFromParcel(in);
    }

    public static final Parcelable.Creator<ConnectionWriter> CREATOR = new
            Parcelable.Creator<ConnectionWriter>() {
                public ConnectionWriter createFromParcel(Parcel in) {
                    Log.d(TAG, "new ConnectionWriter");
                    return new ConnectionWriter(in);
                }

                @Override
                public ConnectionWriter[] newArray(int arg0) {
                    return null;
                }           
        };

    public boolean writeBlock(ByteBuffer data, int pos)
            throws IllegalArgumentException, IOException {
        FileChannel fc = fos.getChannel();


        Log.d(TAG, "ByteBuffer capacity : "+data.capacity());
        Log.d(TAG, "location to write : "+pos*blocksize);
        Log.d(TAG, "FileChannel : "+fc.isOpen() + fc.position() + fc.size());
        int len = fc.write(data);
        Log.d(TAG, "block write in ashmem : "+len + " fd: "+fd);
        return true;
    }

    public void writeToParcel(Parcel out, int arg1) {
        Log.d(TAG, "writeToParcel "+ "fd: "+fd + " fd valid"+ fd.valid());

        out.writeInt(blocksize);
        out.writeInt(noofBlocks);
        out.writeFileDescriptor(fd);
        out.writeInt(lastPosition);
        out.writeInt(chanId);
    }

    public void readFromParcel(Parcel in) {
        // Make sure to validate data since these are coming from an external process
        blocksize = in.readInt();
        noofBlocks = in.readInt();
        ParcelFileDescriptor pfd = in.readFileDescriptor();
        if (pfd != null) {
            fd = pfd.getFileDescriptor();
            Log.d(TAG, "readFromParcel "+ "fd: "+fd);
            fos = new FileOutputStream(fd);
            Log.v(TAG, "  fd is " + fd.valid());
            long stat = pfd.getStatSize();
            Log.d(TAG, "  fd stat " + stat);
        }
        lastPosition = in.readInt();
        chanId = in.readInt();
    }

    public int getId() {
        return chanId;
    }

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    public void close() {
        try {
            if (fos != null)
                fos.close();
        } catch (IOException ioe) {
        }
    }
}

adb logcat

ConnectionWriter(31694): new ConnectionWriter
ConnectionWriter(31694): readFromParcel fd: FileDescriptor[58]
ConnectionWriter(31694):   fd is true
ConnectionWriter(31694):   fd stat -1
ConnectionWriter(31694): ByteBuffer capacity : 128
ConnectionWriter(31694): location to write : 0
ConnectionWriter(31694): FileChannel : true00
ConnectionWriter(31694): block write in ashmem : 0 fd: FileDescriptor[58]

, , ParcelFileDescriptor. - FFD. , .

+4

All Articles