blob: 428b87cd51a3352858a3db76a9535387187551c6 [file] [log] [blame]
Mike Lockwood94afecf2012-10-24 10:45:23 -07001/*
Mathias Agopian002e1e52013-05-06 20:20:50 -07002 * Copyright 2013 The Android Open Source Project
Mike Lockwood94afecf2012-10-24 10:45:23 -07003 *
Mathias Agopian002e1e52013-05-06 20:20:50 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Mike Lockwood94afecf2012-10-24 10:45:23 -070015 */
Mathias Agopian002e1e52013-05-06 20:20:50 -070016
Mike Lockwood94afecf2012-10-24 10:45:23 -070017#include <binder/Parcel.h>
18#include <binder/ProcessState.h>
19#include <binder/IServiceManager.h>
Mathias Agopian002e1e52013-05-06 20:20:50 -070020#include <binder/TextOutput.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070021
22#include <getopt.h>
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <unistd.h>
27#include <sys/time.h>
28
29using namespace android;
30
31void writeString16(Parcel& parcel, const char* string)
32{
33 if (string != NULL)
34 {
35 parcel.writeString16(String16(string));
36 }
37 else
38 {
39 parcel.writeInt32(-1);
40 }
41}
42
43// get the name of the generic interface we hold a reference to
44static String16 get_interface_name(sp<IBinder> service)
45{
46 if (service != NULL) {
47 Parcel data, reply;
48 status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);
49 if (err == NO_ERROR) {
50 return reply.readString16();
51 }
52 }
53 return String16();
54}
55
56static String8 good_old_string(const String16& src)
57{
58 String8 name8;
59 char ch8[2];
60 ch8[1] = 0;
61 for (unsigned j = 0; j < src.size(); j++) {
62 char16_t ch = src[j];
63 if (ch < 128) ch8[0] = (char)ch;
64 name8.append(ch8);
65 }
66 return name8;
67}
68
69int main(int argc, char* const argv[])
70{
71 sp<IServiceManager> sm = defaultServiceManager();
72 fflush(stdout);
73 if (sm == NULL) {
74 aerr << "service: Unable to get default service manager!" << endl;
75 return 20;
76 }
77
78 bool wantsUsage = false;
79 int result = 0;
80
81 while (1) {
82 int ic = getopt(argc, argv, "h?");
83 if (ic < 0)
84 break;
85
86 switch (ic) {
87 case 'h':
88 case '?':
89 wantsUsage = true;
90 break;
91 default:
92 aerr << "service: Unknown option -" << ic << endl;
93 wantsUsage = true;
94 result = 10;
95 break;
96 }
97 }
98
99 if (optind >= argc) {
100 wantsUsage = true;
101 } else if (!wantsUsage) {
102 if (strcmp(argv[optind], "check") == 0) {
103 optind++;
104 if (optind < argc) {
105 sp<IBinder> service = sm->checkService(String16(argv[optind]));
106 aout << "Service " << argv[optind] <<
107 (service == NULL ? ": not found" : ": found") << endl;
108 } else {
109 aerr << "service: No service specified for check" << endl;
110 wantsUsage = true;
111 result = 10;
112 }
113 }
114 else if (strcmp(argv[optind], "list") == 0) {
115 Vector<String16> services = sm->listServices();
116 aout << "Found " << services.size() << " services:" << endl;
117 for (unsigned i = 0; i < services.size(); i++) {
118 String16 name = services[i];
119 sp<IBinder> service = sm->checkService(name);
120 aout << i
121 << "\t" << good_old_string(name)
122 << ": [" << good_old_string(get_interface_name(service)) << "]"
123 << endl;
124 }
125 } else if (strcmp(argv[optind], "call") == 0) {
126 optind++;
127 if (optind+1 < argc) {
128 int serviceArg = optind;
129 sp<IBinder> service = sm->checkService(String16(argv[optind++]));
130 String16 ifName = get_interface_name(service);
131 int32_t code = atoi(argv[optind++]);
132 if (service != NULL && ifName.size() > 0) {
133 Parcel data, reply;
134
135 // the interface name is first
136 data.writeInterfaceToken(ifName);
137
138 // then the rest of the call arguments
139 while (optind < argc) {
140 if (strcmp(argv[optind], "i32") == 0) {
141 optind++;
142 if (optind >= argc) {
143 aerr << "service: no integer supplied for 'i32'" << endl;
144 wantsUsage = true;
145 result = 10;
146 break;
147 }
148 data.writeInt32(atoi(argv[optind++]));
Jeff Brownd46898f2015-04-06 19:42:43 -0700149 } else if (strcmp(argv[optind], "i64") == 0) {
150 optind++;
151 if (optind >= argc) {
152 aerr << "service: no integer supplied for 'i64'" << endl;
153 wantsUsage = true;
154 result = 10;
155 break;
156 }
157 data.writeInt64(atoll(argv[optind++]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700158 } else if (strcmp(argv[optind], "s16") == 0) {
159 optind++;
160 if (optind >= argc) {
161 aerr << "service: no string supplied for 's16'" << endl;
162 wantsUsage = true;
163 result = 10;
164 break;
165 }
166 data.writeString16(String16(argv[optind++]));
Jeff Brownd46898f2015-04-06 19:42:43 -0700167 } else if (strcmp(argv[optind], "f") == 0) {
168 optind++;
169 if (optind >= argc) {
170 aerr << "service: no number supplied for 'f'" << endl;
171 wantsUsage = true;
172 result = 10;
173 break;
174 }
175 data.writeFloat(atof(argv[optind++]));
176 } else if (strcmp(argv[optind], "d") == 0) {
177 optind++;
178 if (optind >= argc) {
179 aerr << "service: no number supplied for 'd'" << endl;
180 wantsUsage = true;
181 result = 10;
182 break;
183 }
184 data.writeDouble(atof(argv[optind++]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700185 } else if (strcmp(argv[optind], "null") == 0) {
186 optind++;
187 data.writeStrongBinder(NULL);
188 } else if (strcmp(argv[optind], "intent") == 0) {
189
190 char* action = NULL;
191 char* dataArg = NULL;
192 char* type = NULL;
193 int launchFlags = 0;
194 char* component = NULL;
195 int categoryCount = 0;
196 char* categories[16];
197
198 char* context1 = NULL;
199
200 optind++;
201
202 while (optind < argc)
203 {
204 char* key = strtok_r(argv[optind], "=", &context1);
205 char* value = strtok_r(NULL, "=", &context1);
206
207 // we have reached the end of the XXX=XXX args.
208 if (key == NULL) break;
209
210 if (strcmp(key, "action") == 0)
211 {
212 action = value;
213 }
214 else if (strcmp(key, "data") == 0)
215 {
216 dataArg = value;
217 }
218 else if (strcmp(key, "type") == 0)
219 {
220 type = value;
221 }
222 else if (strcmp(key, "launchFlags") == 0)
223 {
224 launchFlags = atoi(value);
225 }
226 else if (strcmp(key, "component") == 0)
227 {
228 component = value;
229 }
230 else if (strcmp(key, "categories") == 0)
231 {
232 char* context2 = NULL;
233 int categoryCount = 0;
234 categories[categoryCount] = strtok_r(value, ",", &context2);
235
236 while (categories[categoryCount] != NULL)
237 {
238 categoryCount++;
239 categories[categoryCount] = strtok_r(NULL, ",", &context2);
240 }
241 }
242
243 optind++;
244 }
245
246 writeString16(data, action);
247 writeString16(data, dataArg);
248 writeString16(data, type);
249 data.writeInt32(launchFlags);
250 writeString16(data, component);
251
252 if (categoryCount > 0)
253 {
254 data.writeInt32(categoryCount);
255 for (int i = 0 ; i < categoryCount ; i++)
256 {
257 writeString16(data, categories[i]);
258 }
259 }
260 else
261 {
262 data.writeInt32(0);
263 }
264
265 // for now just set the extra field to be null.
266 data.writeInt32(-1);
267 } else {
268 aerr << "service: unknown option " << argv[optind] << endl;
269 wantsUsage = true;
270 result = 10;
271 break;
272 }
273 }
274
275 service->transact(code, data, &reply);
276 aout << "Result: " << reply << endl;
277 } else {
278 aerr << "service: Service " << argv[serviceArg]
279 << " does not exist" << endl;
280 result = 10;
281 }
282 } else {
283 if (optind < argc) {
284 aerr << "service: No service specified for call" << endl;
285 } else {
286 aerr << "service: No code specified for call" << endl;
287 }
288 wantsUsage = true;
289 result = 10;
290 }
291 } else {
292 aerr << "service: Unknown command " << argv[optind] << endl;
293 wantsUsage = true;
294 result = 10;
295 }
296 }
297
298 if (wantsUsage) {
299 aout << "Usage: service [-h|-?]\n"
300 " service list\n"
301 " service check SERVICE\n"
Jeff Brownd46898f2015-04-06 19:42:43 -0700302 " service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...\n"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700303 "Options:\n"
Jeff Brownd46898f2015-04-06 19:42:43 -0700304 " i32: Write the 32-bit integer N into the send parcel.\n"
305 " i64: Write the 64-bit integer N into the send parcel.\n"
306 " f: Write the 32-bit single-precision number N into the send parcel.\n"
307 " d: Write the 64-bit double-precision number N into the send parcel.\n"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700308 " s16: Write the UTF-16 string STR into the send parcel.\n";
309// " intent: Write and Intent int the send parcel. ARGS can be\n"
310// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
311 return result;
312 }
313
314 return result;
315}
316