android—调试命令service

在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 sm = defaultServiceManager();

    //② 调用service check SERVICE
        if (strcmp(argv[optind], "check") == 0) {
            optind++;
            if (optind < argc) {
                sp 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 services = sm->listServices();
            aout << "Found " << services.size() << " services:" << endl;
            for (unsigned i = 0; i < services.size(); i++) {
                String16 name = services[i];
                sp 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 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

你可能感兴趣的:(android—调试命令service)