frameworks/native/cmds/service/service.cpp
sp<IServiceManager> sm = defaultServiceManager();
if (strcmp(argv[optind], "list") == 0) {
Vector<String16> services = sm->listServices();
aout << "Found " << services.size() << " services:" << endl;
for (unsigned i = 0; i < services.size(); i++) {
String16 name = services[i];
sp<IBinder> service = sm->checkService(name);
aout << i
<< "\t" << good_old_string(name)
<< ": [" << good_old_string(get_interface_name(service)) << "]"
<< endl;
}
返回的service name 和 interface name: 比如:
activity: [android.app.IActivityManager]
注意sm返回的是String16, 而native层表示字符使用的是String8, 需要进行转换
把由2个字节表示一个字符,转化成一个字符
static String8 good_old_string(const String16& src)
{
String8 name8;
char ch8[2];
ch8[1] = 0;
for (unsigned j = 0; j < src.size(); j++) {
char16_t ch = src[j];
if (ch < 128) ch8[0] = (char)ch;【强制类型转化】
name8.append(ch8);
}
return name8;
}
Native 实现的 service 的名字和接口名赋值:
const String8 xxxProxy::SName = String8("xxx");
const char* xxxProxy::getServiceName() {
return SName;
}
IMPLEMENT_META_INTERFACE(xxxService, "接口名字");
String16::String16(const char* o)
: mString(allocFromUTF8(o, strlen(o)))
{
}
static char16_t* allocFromUTF8(const char* u8str, size_t u8len)
{
if (u8len == 0) return getEmptyString();
const uint8_t* u8cur = (const uint8_t*) u8str;
const ssize_t u16len = utf8_to_utf16_length(u8cur, u8len);
if (u16len < 0) {
return getEmptyString();
}
SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t)*(u16len+1));
if (buf) {
u8cur = (const uint8_t*) u8str;
char16_t* u16str = (char16_t*)buf->data();
utf8_to_utf16(u8cur, u8len, u16str);
//printf("Created UTF-16 string from UTF-8 \"%s\":", in);
//printHexData(1, str, buf->size(), 16, 1);
//printf("\n");
return u16str;
}
return getEmptyString();
}
/*utf8到utf16并不是简单的长度×2*/
ssize_t utf8_to_utf16_length(const uint8_t* u8str, size_t u8len)
{
const uint8_t* const u8end = u8str + u8len;
const uint8_t* u8cur = u8str;
/* Validate that the UTF-8 is the correct len */
size_t u16measuredLen = 0;
while (u8cur < u8end) {
u16measuredLen++;
int u8charLen = utf8_codepoint_len(*u8cur);
uint32_t codepoint = utf8_to_utf32_codepoint(u8cur, u8charLen);
if (codepoint > 0xFFFF) u16measuredLen++; // this will be a surrogate pair in utf16
u8cur += u8charLen;
}
/**
* Make sure that we ended where we thought we would and the output UTF-16
* will be exactly how long we were told it would be.
*/
if (u8cur != u8end) {
return -1;
}
return u16measuredLen;
}
Unicode的最初目标,是用1个16位的编码来为超过65000字符提供映射。但这还不够,
它不能覆盖全部历史上的文字,也不能解决传输的问题(implantation head-ache's),
尤其在那些基于网络的应用中。已有的软件必须做大量的工作来程序16位的数据。
因此,Unicode用一些基本的保留字符制定了三套编码方式。它们分别是UTF-8,UTF-16和UTF-32。
正如名字所示,在UTF-8中,字符是以8位序列来编码的,用一个或几个字节来表示一个字符。
这种方式的最大好处,是UTF-8保留了ASCII字符的编码做为它的一部分,例如,在UTF-8和ASCII中,“A”的编码都是0x41.
UTF-16和UTF-32分别是Unicode的16位和32位编码方式。
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
The getopt() function parses the command-line arguments. Its arguments argc and argv are the argument count
and array as passed to the main() function on program invocation. An element of
argv that starts with '-' (and is not exactly "-" or "--") is an option element.
The characters of this element (aside from the initial '-') are option characters. If getopt() is called
repeatedly, it returns successively each of the option characters from each of the option elements.
The variable optind is the index of the next element to be processed in argv.
The system initializes this value to 1. The caller can reset it to 1 to restart scanning of the same argv, or
when scanning a new argument vector.
If getopt() finds another option character, it returns that character, updating the external variable optind and
a static variable nextchar so that the next call to getopt() can resume the
scan with the following option character or argv-element.
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
sp<IBinder> service = sm->checkService(String16(argv[optind]));
aout << "Service " << argv[optind] <<
(service == NULL ? ": not found" : ": found") << endl;
int main(int argc, char* const argv[])
{
sp<IServiceManager> sm = defaultServiceManager();
while (1) {
int ic = getopt(argc, argv, "h?");
if (ic < 0)
break;
switch (ic) {
case 'h':
case '?':
wantsUsage = true;
break;
}
}
if (strcmp(argv[optind], "check") == 0) {
optind++;
if (optind < argc) {/*从名字得到接口IBinder*/
sp<IBinder> service = sm->checkService(String16(argv[optind]));
aout << "Service " << argv[optind] <<
(service == NULL ? ": not found" : ": found") << endl;
}
}
else if (strcmp(argv[optind], "list") == 0) {
Vector<String16> services = sm->listServices();
aout << "Found " << services.size() << " services:" << endl;
for (unsigned i = 0; i < services.size(); i++) {
String16 name = services[i];
sp<IBinder> service = sm->checkService(name);
aout << i
<< "\t" << good_old_string(name)/*服务的名字、对应的接口名*/
<< ": [" << good_old_string(get_interface_name(service)) << "]"
<< endl;
}
} else if (strcmp(argv[optind], "call") == 0) {
optind++;
if (optind+1 < argc) {
int serviceArg = optind;
sp<IBinder> service = sm->checkService(String16(argv[optind++]));
String16 ifName = get_interface_name(service);
int32_t code = atoi(argv[optind++]);
if (service != NULL && ifName.size() > 0) {
Parcel data, reply;
// the interface name is first
data.writeInterfaceToken(ifName);
// then the rest of the call arguments
while (optind < argc) {
if (strcmp(argv[optind], "i32") == 0) {
optind++;
if (optind >= argc) {
aerr << "service: no integer supplied for 'i32'" << endl;
wantsUsage = true;
result = 10;
break;
}
data.writeInt32(atoi(argv[optind++]));
} else if (strcmp(argv[optind], "intent") == 0) {
char* action = NULL;
char* dataArg = NULL;
char* type = NULL;
int launchFlags = 0;
char* component = NULL;
int categoryCount = 0;
char* categories[16];
char* context1 = NULL;
while (optind < argc)
{
char* key = strtok_r(argv[optind], "=", &context1);
char* value = strtok_r(NULL, "=", &context1);
// we have reached the end of the XXX=XXX args.
if (key == NULL) break;
if (strcmp(key, "action") == 0)
{
action = value;
}
else if (strcmp(key, "data") == 0)
{
dataArg = value;
}
else if (strcmp(key, "type") == 0)
{
type = value;
}
else if (strcmp(key, "launchFlags") == 0)
{
launchFlags = atoi(value);
}
else if (strcmp(key, "component") == 0)
{
component = value;
}
else if (strcmp(key, "categories") == 0)
{
char* context2 = NULL;
int categoryCount = 0;
categories[categoryCount] = strtok_r(value, ",", &context2);
while (categories[categoryCount] != NULL)
{
categoryCount++;
categories[categoryCount] = strtok_r(NULL, ",", &context2);
}
}
optind++;
}
writeString16(data, action);
writeString16(data, dataArg);
writeString16(data, type);
data.writeInt32(launchFlags);
writeString16(data, component);
if (categoryCount > 0)
{
data.writeInt32(categoryCount);
for (int i = 0 ; i < categoryCount ; i++)
{
writeString16(data, categories[i]);
}
}
else
{
data.writeInt32(0);
}
// for now just set the extra field to be null.
data.writeInt32(-1);
} else {
aerr << "service: unknown option " << argv[optind] << endl;
wantsUsage = true;
result = 10;
break;
}
}
service->transact(code, data, &reply);
aout << "Result: " << reply << endl;
}
java实现的服务还不知道?
sp<IServiceManager> sm = defaultServiceManager();
if (strcmp(argv[optind], "list") == 0) {
Vector<String16> services = sm->listServices();
aout << "Found " << services.size() << " services:" << endl;
for (unsigned i = 0; i < services.size(); i++) {
String16 name = services[i];
sp<IBinder> service = sm->checkService(name);
aout << i
<< "\t" << good_old_string(name)
<< ": [" << good_old_string(get_interface_name(service)) << "]"
<< endl;
}
返回的service name 和 interface name: 比如:
activity: [android.app.IActivityManager]
注意sm返回的是String16, 而native层表示字符使用的是String8, 需要进行转换
把由2个字节表示一个字符,转化成一个字符
static String8 good_old_string(const String16& src)
{
String8 name8;
char ch8[2];
ch8[1] = 0;
for (unsigned j = 0; j < src.size(); j++) {
char16_t ch = src[j];
if (ch < 128) ch8[0] = (char)ch;【强制类型转化】
name8.append(ch8);
}
return name8;
}
Native 实现的 service 的名字和接口名赋值:
const String8 xxxProxy::SName = String8("xxx");
const char* xxxProxy::getServiceName() {
return SName;
}
IMPLEMENT_META_INTERFACE(xxxService, "接口名字");
String16::String16(const char* o)
: mString(allocFromUTF8(o, strlen(o)))
{
}
static char16_t* allocFromUTF8(const char* u8str, size_t u8len)
{
if (u8len == 0) return getEmptyString();
const uint8_t* u8cur = (const uint8_t*) u8str;
const ssize_t u16len = utf8_to_utf16_length(u8cur, u8len);
if (u16len < 0) {
return getEmptyString();
}
SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t)*(u16len+1));
if (buf) {
u8cur = (const uint8_t*) u8str;
char16_t* u16str = (char16_t*)buf->data();
utf8_to_utf16(u8cur, u8len, u16str);
//printf("Created UTF-16 string from UTF-8 \"%s\":", in);
//printHexData(1, str, buf->size(), 16, 1);
//printf("\n");
return u16str;
}
return getEmptyString();
}
/*utf8到utf16并不是简单的长度×2*/
ssize_t utf8_to_utf16_length(const uint8_t* u8str, size_t u8len)
{
const uint8_t* const u8end = u8str + u8len;
const uint8_t* u8cur = u8str;
/* Validate that the UTF-8 is the correct len */
size_t u16measuredLen = 0;
while (u8cur < u8end) {
u16measuredLen++;
int u8charLen = utf8_codepoint_len(*u8cur);
uint32_t codepoint = utf8_to_utf32_codepoint(u8cur, u8charLen);
if (codepoint > 0xFFFF) u16measuredLen++; // this will be a surrogate pair in utf16
u8cur += u8charLen;
}
/**
* Make sure that we ended where we thought we would and the output UTF-16
* will be exactly how long we were told it would be.
*/
if (u8cur != u8end) {
return -1;
}
return u16measuredLen;
}
Unicode的最初目标,是用1个16位的编码来为超过65000字符提供映射。但这还不够,
它不能覆盖全部历史上的文字,也不能解决传输的问题(implantation head-ache's),
尤其在那些基于网络的应用中。已有的软件必须做大量的工作来程序16位的数据。
因此,Unicode用一些基本的保留字符制定了三套编码方式。它们分别是UTF-8,UTF-16和UTF-32。
正如名字所示,在UTF-8中,字符是以8位序列来编码的,用一个或几个字节来表示一个字符。
这种方式的最大好处,是UTF-8保留了ASCII字符的编码做为它的一部分,例如,在UTF-8和ASCII中,“A”的编码都是0x41.
UTF-16和UTF-32分别是Unicode的16位和32位编码方式。
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
The getopt() function parses the command-line arguments. Its arguments argc and argv are the argument count
and array as passed to the main() function on program invocation. An element of
argv that starts with '-' (and is not exactly "-" or "--") is an option element.
The characters of this element (aside from the initial '-') are option characters. If getopt() is called
repeatedly, it returns successively each of the option characters from each of the option elements.
The variable optind is the index of the next element to be processed in argv.
The system initializes this value to 1. The caller can reset it to 1 to restart scanning of the same argv, or
when scanning a new argument vector.
If getopt() finds another option character, it returns that character, updating the external variable optind and
a static variable nextchar so that the next call to getopt() can resume the
scan with the following option character or argv-element.
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
sp<IBinder> service = sm->checkService(String16(argv[optind]));
aout << "Service " << argv[optind] <<
(service == NULL ? ": not found" : ": found") << endl;
int main(int argc, char* const argv[])
{
sp<IServiceManager> sm = defaultServiceManager();
while (1) {
int ic = getopt(argc, argv, "h?");
if (ic < 0)
break;
switch (ic) {
case 'h':
case '?':
wantsUsage = true;
break;
}
}
if (strcmp(argv[optind], "check") == 0) {
optind++;
if (optind < argc) {/*从名字得到接口IBinder*/
sp<IBinder> service = sm->checkService(String16(argv[optind]));
aout << "Service " << argv[optind] <<
(service == NULL ? ": not found" : ": found") << endl;
}
}
else if (strcmp(argv[optind], "list") == 0) {
Vector<String16> services = sm->listServices();
aout << "Found " << services.size() << " services:" << endl;
for (unsigned i = 0; i < services.size(); i++) {
String16 name = services[i];
sp<IBinder> service = sm->checkService(name);
aout << i
<< "\t" << good_old_string(name)/*服务的名字、对应的接口名*/
<< ": [" << good_old_string(get_interface_name(service)) << "]"
<< endl;
}
} else if (strcmp(argv[optind], "call") == 0) {
optind++;
if (optind+1 < argc) {
int serviceArg = optind;
sp<IBinder> service = sm->checkService(String16(argv[optind++]));
String16 ifName = get_interface_name(service);
int32_t code = atoi(argv[optind++]);
if (service != NULL && ifName.size() > 0) {
Parcel data, reply;
// the interface name is first
data.writeInterfaceToken(ifName);
// then the rest of the call arguments
while (optind < argc) {
if (strcmp(argv[optind], "i32") == 0) {
optind++;
if (optind >= argc) {
aerr << "service: no integer supplied for 'i32'" << endl;
wantsUsage = true;
result = 10;
break;
}
data.writeInt32(atoi(argv[optind++]));
} else if (strcmp(argv[optind], "intent") == 0) {
char* action = NULL;
char* dataArg = NULL;
char* type = NULL;
int launchFlags = 0;
char* component = NULL;
int categoryCount = 0;
char* categories[16];
char* context1 = NULL;
while (optind < argc)
{
char* key = strtok_r(argv[optind], "=", &context1);
char* value = strtok_r(NULL, "=", &context1);
// we have reached the end of the XXX=XXX args.
if (key == NULL) break;
if (strcmp(key, "action") == 0)
{
action = value;
}
else if (strcmp(key, "data") == 0)
{
dataArg = value;
}
else if (strcmp(key, "type") == 0)
{
type = value;
}
else if (strcmp(key, "launchFlags") == 0)
{
launchFlags = atoi(value);
}
else if (strcmp(key, "component") == 0)
{
component = value;
}
else if (strcmp(key, "categories") == 0)
{
char* context2 = NULL;
int categoryCount = 0;
categories[categoryCount] = strtok_r(value, ",", &context2);
while (categories[categoryCount] != NULL)
{
categoryCount++;
categories[categoryCount] = strtok_r(NULL, ",", &context2);
}
}
optind++;
}
writeString16(data, action);
writeString16(data, dataArg);
writeString16(data, type);
data.writeInt32(launchFlags);
writeString16(data, component);
if (categoryCount > 0)
{
data.writeInt32(categoryCount);
for (int i = 0 ; i < categoryCount ; i++)
{
writeString16(data, categories[i]);
}
}
else
{
data.writeInt32(0);
}
// for now just set the extra field to be null.
data.writeInt32(-1);
} else {
aerr << "service: unknown option " << argv[optind] << endl;
wantsUsage = true;
result = 10;
break;
}
}
service->transact(code, data, &reply);
aout << "Result: " << reply << endl;
}
java实现的服务还不知道?