Saturday, April 25, 2015

Android Native System - Getting a native fd for a content provider file

In case of Android native programming, there can be a situation when we have to retrieve an fd(file descriptor for performing C/C++ I/O), below is  line-by-line explanation of such a code snippet from AOSP,

Background

We know that Activity is the heart of Android application framework so ActivityManager Service, most important Android System service which handles activity/task, intent, file, permission, memory etc. related things.

So it can be simplified in three steps as below:
1. Get ActivityManager Service.
2. Pass the URI data to service on OPEN_CONTENT_URI_TRANSACTION transaction.
3. Get the fd from reply.

Implementation

const uint32_t OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 4;

// Perform ContentProvider.openFile() on the given URI, returning
// the resulting native file descriptor.  Returns < 0 on error.
int openContentProviderFile(const String16& uri)
{
    int fd = -1;
    
    //Step 1
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> am = sm->getService(String16("activity"));

    if (am != NULL) {
        Parcel data, reply;
        
        //Step 2
        data.writeInterfaceToken(String16("android.app.IActivityManager"));
        data.writeString16(uri);
        status_t ret = am->transact(OPEN_CONTENT_URI_TRANSACTION, data, &reply);

        if (ret == NO_ERROR) {
            int32_t exceptionCode = reply.readExceptionCode();
            if (!exceptionCode) {
                // Success is indicated here by a nonzero int followed by the fd;
                // failure by a zero int with no data following.
                if (reply.readInt32() != 0) {
                
                //Step3
                    fd = dup(reply.readFileDescriptor());
                }
            } else {
                // An exception was thrown back; fall through to return failure
                ALOGD("openContentUri(%s) caught exception %d\n",
                        String8(uri).string(), exceptionCode);
            }
        }
    }
    return fd;
}


No comments:

Post a Comment