blob: 32db83ba1dcb19b160ab76e4da78392e5cbdb2a8 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Command line access to services.
3 *
4 */
5
Mathias Agopian07952722009-05-19 19:08:10 -07006#include <binder/Parcel.h>
7#include <binder/ProcessState.h>
8#include <binder/IServiceManager.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009#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