在android中,可以利用service命令去做很多调试工作,例如service list
命令显示系统当前所有在service manager注册的service,其命令具体使用如下,
# service
service
Usage: service [-h|-?]
service list
service check SERVICE
service call SERVICE CODE [i32 INT | s16 STR] ...
Options:
i32: Write the integer INT into the send parcel.
s16: Write the UTF-16 string STR into the send parcel.
主要用法有三个:
1.service list,显示系统当前所有在service manager注册的service;
2.service check SERVICE,查询SERVICE是否存在;
3.service call SERVICE,可以通过binder给service发送code,还可以向service发送intent等,具体代码分析如下。
代码在frameworks\native\cmds\service\service.cpp
,其makefile为
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
service.cpp
LOCAL_SHARED_LIBRARIES := libutils libbinder
ifeq ($(TARGET_OS),linux)
LOCAL_CFLAGS += -DXP_UNIX
#LOCAL_SHARED_LIBRARIES += librt
endif
#编译为应用程序service
LOCAL_MODULE:= service
include $(BUILD_EXECUTABLE)
在main()函数中,
int main(int argc, char* const argv[])
{
//① 获取service manager的BpServiceManager
sp<IServiceManager> sm = defaultServiceManager();
//② 调用service check SERVICE
if (strcmp(argv[optind], "check") == 0) {
optind++;
if (optind < argc) {
sp<IBinder> service = sm->checkService(String16(argv[optind]));
aout << "Service " << argv[optind] <<
(service == NULL ? ": not found" : ": found") << endl;
} else {
aerr << "service: No service specified for check" << endl;
wantsUsage = true;
result = 10;
}
}
//③ 调用service list
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;
}
}
//④ 调用service call
else if (strcmp(argv[optind], "call") == 0) {
optind++;
if (optind+1 < argc) {
int serviceArg = optind;
//获取service的BpBinder
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) {
//传递int
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++]));
}//传递string
else if (strcmp(argv[optind], "s16") == 0) {
optind++;
if (optind >= argc) {
aerr << "service: no string supplied for 's16'" << endl;
wantsUsage = true;
result = 10;
break;
}
data.writeString16(String16(argv[optind++]));
}//传递个null,只写个StrongBinder
else if (strcmp(argv[optind], "null") == 0) {
optind++;
data.writeStrongBinder(NULL);
} //还能发送intent,这个应该是发送给ActivityManagerService
//然后ActivityManagerService将intent重组,
//启动需要的activity等
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;
optind++;
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;
}
}
//直接在BpBinder上调用transact,发送code
service->transact(code, data, &reply);
aout << "Result: " << reply << endl;
}
}
上面代码主要包括4部分:
1.获取service manager的代理对象BpServiceManager;
2.调用service check SERVICE,其实就是调用BpServiceManager->checkService
;
3.调用service list,其实就是调用BpServiceManager->listServices
;
4.调用service call,首先去获取service的BpBinder,后续直接调用transact函数向service发送code,其中命令参数可以包含i32(int),s16(string),null,intent(intent后需要自己组织intent的参数,这个应该是发送给ActivityManagerService,然后ActivityManagerService将intent重组,启动需要的activity)。
举个call的例子,在《android graphic(9)—开发者选项关闭HW overlays 》中分析了通过开发者选项关闭HW overlays,这里也可以通过service 命令向SurfaceFlinger命令发送1008的code。
//关闭HW overlays,code为1008,一个参数为int的1
# service call SurfaceFlinger 1008 i32 1