service.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/*
2 * Command line access to services.
3 *
4 */
5
6#include <utils/Parcel.h>
7#include <utils/ProcessState.h>
8#include <utils/IServiceManager.h>
9#include <utils/TextOutput.h>
10
11#include <getopt.h>
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15#include <unistd.h>
16#include <sys/time.h>
17
18using namespace android;
19
20void writeString16(Parcel& parcel, const char* string)
21{
22    if (string != NULL)
23    {
24        parcel.writeString16(String16(string));
25    }
26    else
27    {
28        parcel.writeInt32(-1);
29    }
30}
31
32// get the name of the generic interface we hold a reference to
33static String16 get_interface_name(sp<IBinder> service)
34{
35    if (service != NULL) {
36        Parcel data, reply;
37        status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);
38        if (err == NO_ERROR) {
39            return reply.readString16();
40        }
41    }
42    return String16();
43}
44
45static String8 good_old_string(const String16& src)
46{
47    String8 name8;
48    char ch8[2];
49    ch8[1] = 0;
50    for (unsigned j = 0; j < src.size(); j++) {
51        char16_t ch = src[j];
52        if (ch < 128) ch8[0] = (char)ch;
53        name8.append(ch8);
54    }
55    return name8;
56}
57
58int main(int argc, char* const argv[])
59{
60    sp<IServiceManager> sm = defaultServiceManager();
61    fflush(stdout);
62    if (sm == NULL) {
63        aerr << "service: Unable to get default service manager!" << endl;
64        return 20;
65    }
66
67    bool wantsUsage = false;
68    int result = 0;
69
70    while (1) {
71        int ic = getopt(argc, argv, "h?");
72        if (ic < 0)
73            break;
74
75        switch (ic) {
76        case 'h':
77        case '?':
78            wantsUsage = true;
79            break;
80        default:
81            aerr << "service: Unknown option -" << ic << endl;
82            wantsUsage = true;
83            result = 10;
84            break;
85        }
86    }
87
88    if (optind >= argc) {
89        wantsUsage = true;
90    } else if (!wantsUsage) {
91        if (strcmp(argv[optind], "check") == 0) {
92            optind++;
93            if (optind < argc) {
94                sp<IBinder> service = sm->checkService(String16(argv[optind]));
95                aout << "Service " << argv[optind] <<
96                    (service == NULL ? ": not found" : ": found") << endl;
97            } else {
98                aerr << "service: No service specified for check" << endl;
99                wantsUsage = true;
100                result = 10;
101            }
102        }
103        else if (strcmp(argv[optind], "list") == 0) {
104            Vector<String16> services = sm->listServices();
105            aout << "Found " << services.size() << " services:" << endl;
106            for (unsigned i = 0; i < services.size(); i++) {
107                String16 name = services[i];
108                sp<IBinder> service = sm->checkService(name);
109                aout << i
110                     << "\t" << good_old_string(name)
111                     << ": [" << good_old_string(get_interface_name(service)) << "]"
112                     << endl;
113            }
114        } else if (strcmp(argv[optind], "call") == 0) {
115            optind++;
116            if (optind+1 < argc) {
117                int serviceArg = optind;
118                sp<IBinder> service = sm->checkService(String16(argv[optind++]));
119                String16 ifName = get_interface_name(service);
120                int32_t code = atoi(argv[optind++]);
121                if (service != NULL && ifName.size() > 0) {
122                    Parcel data, reply;
123
124                    // the interface name is first
125                    data.writeInterfaceToken(ifName);
126
127                    // then the rest of the call arguments
128                    while (optind < argc) {
129                        if (strcmp(argv[optind], "i32") == 0) {
130                            optind++;
131                            if (optind >= argc) {
132                                aerr << "service: no integer supplied for 'i32'" << endl;
133                                wantsUsage = true;
134                                result = 10;
135                                break;
136                            }
137                            data.writeInt32(atoi(argv[optind++]));
138                        } else if (strcmp(argv[optind], "s16") == 0) {
139                            optind++;
140                            if (optind >= argc) {
141                                aerr << "service: no string supplied for 's16'" << endl;
142                                wantsUsage = true;
143                                result = 10;
144                                break;
145                            }
146                            data.writeString16(String16(argv[optind++]));
147                        } else if (strcmp(argv[optind], "null") == 0) {
148                            optind++;
149                            data.writeStrongBinder(NULL);
150                        } else if (strcmp(argv[optind], "intent") == 0) {
151
152                        	char* action = NULL;
153                        	char* dataArg = NULL;
154                        	char* type = NULL;
155                        	int launchFlags = 0;
156                        	char* component = NULL;
157                        	int categoryCount = 0;
158                        	char* categories[16];
159
160                        	char* context1 = NULL;
161
162                            optind++;
163
164                        	while (optind < argc)
165                        	{
166                        		char* key = strtok_r(argv[optind], "=", &context1);
167                        		char* value = strtok_r(NULL, "=", &context1);
168
169                                // we have reached the end of the XXX=XXX args.
170                                if (key == NULL) break;
171
172                        		if (strcmp(key, "action") == 0)
173                        		{
174                        			action = value;
175                        		}
176                        		else if (strcmp(key, "data") == 0)
177                        		{
178                        			dataArg = value;
179                        		}
180                        		else if (strcmp(key, "type") == 0)
181                        		{
182                        			type = value;
183                        		}
184                        		else if (strcmp(key, "launchFlags") == 0)
185                        		{
186                        			launchFlags = atoi(value);
187                        		}
188                        		else if (strcmp(key, "component") == 0)
189                        		{
190                        			component = value;
191                        		}
192                        		else if (strcmp(key, "categories") == 0)
193                        		{
194                        			char* context2 = NULL;
195                        			int categoryCount = 0;
196                        			categories[categoryCount] = strtok_r(value, ",", &context2);
197
198                        			while (categories[categoryCount] != NULL)
199                        			{
200                        				categoryCount++;
201                        				categories[categoryCount] = strtok_r(NULL, ",", &context2);
202                        			}
203                        		}
204
205                                optind++;
206                        	}
207
208                            writeString16(data, action);
209                            writeString16(data, dataArg);
210                            writeString16(data, type);
211                       		data.writeInt32(launchFlags);
212                            writeString16(data, component);
213
214                            if (categoryCount > 0)
215                            {
216                                data.writeInt32(categoryCount);
217                                for (int i = 0 ; i < categoryCount ; i++)
218                                {
219                                    writeString16(data, categories[i]);
220                                }
221                            }
222                            else
223                            {
224                                data.writeInt32(0);
225                            }
226
227                            // for now just set the extra field to be null.
228                       		data.writeInt32(-1);
229                        } else {
230                            aerr << "service: unknown option " << argv[optind] << endl;
231                            wantsUsage = true;
232                            result = 10;
233                            break;
234                        }
235                    }
236
237                    service->transact(code, data, &reply);
238                    aout << "Result: " << reply << endl;
239                } else {
240                    aerr << "service: Service " << argv[serviceArg]
241                        << " does not exist" << endl;
242                    result = 10;
243                }
244            } else {
245                if (optind < argc) {
246                    aerr << "service: No service specified for call" << endl;
247                } else {
248                    aerr << "service: No code specified for call" << endl;
249                }
250                wantsUsage = true;
251                result = 10;
252            }
253        } else {
254            aerr << "service: Unknown command " << argv[optind] << endl;
255            wantsUsage = true;
256            result = 10;
257        }
258    }
259
260    if (wantsUsage) {
261        aout << "Usage: service [-h|-?]\n"
262                "       service list\n"
263                "       service check SERVICE\n"
264                "       service call SERVICE CODE [i32 INT | s16 STR] ...\n"
265                "Options:\n"
266                "   i32: Write the integer INT into the send parcel.\n"
267                "   s16: Write the UTF-16 string STR into the send parcel.\n";
268//                "   intent: Write and Intent int the send parcel. ARGS can be\n"
269//                "       action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
270        return result;
271    }
272
273    return result;
274}
275
276