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;
}
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