blob: 34a3fdc4201ad8ea516b7260d5239613435efffe [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{
Yi Kong19d5c002018-07-20 13:39:55 -070033 if (string != nullptr)
Mike Lockwood94afecf2012-10-24 10:45:23 -070034 {
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{
Yi Kong19d5c002018-07-20 13:39:55 -070046 if (service != nullptr) {
Mike Lockwood94afecf2012-10-24 10:45:23 -070047 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{
Mike Lockwood94afecf2012-10-24 10:45:23 -070071 bool wantsUsage = false;
72 int result = 0;
73
74 while (1) {
Martijn Coenen3def1f22017-04-07 10:46:57 -070075 int ic = getopt(argc, argv, "h?");
Mike Lockwood94afecf2012-10-24 10:45:23 -070076 if (ic < 0)
77 break;
78
79 switch (ic) {
80 case 'h':
81 case '?':
82 wantsUsage = true;
83 break;
84 default:
85 aerr << "service: Unknown option -" << ic << endl;
86 wantsUsage = true;
87 result = 10;
88 break;
89 }
90 }
Martijn Coenen3def1f22017-04-07 10:46:57 -070091#ifdef VENDORSERVICES
92 ProcessState::initWithDriver("/dev/vndbinder");
93#endif
Martijn Coenend6480ca2017-04-05 14:16:12 -070094 sp<IServiceManager> sm = defaultServiceManager();
95 fflush(stdout);
Yi Kong19d5c002018-07-20 13:39:55 -070096 if (sm == nullptr) {
Martijn Coenend6480ca2017-04-05 14:16:12 -070097 aerr << "service: Unable to get default service manager!" << endl;
98 return 20;
99 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700100
101 if (optind >= argc) {
102 wantsUsage = true;
103 } else if (!wantsUsage) {
104 if (strcmp(argv[optind], "check") == 0) {
105 optind++;
106 if (optind < argc) {
107 sp<IBinder> service = sm->checkService(String16(argv[optind]));
108 aout << "Service " << argv[optind] <<
Yi Kong19d5c002018-07-20 13:39:55 -0700109 (service == nullptr ? ": not found" : ": found") << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700110 } else {
111 aerr << "service: No service specified for check" << endl;
112 wantsUsage = true;
113 result = 10;
114 }
115 }
116 else if (strcmp(argv[optind], "list") == 0) {
117 Vector<String16> services = sm->listServices();
118 aout << "Found " << services.size() << " services:" << endl;
119 for (unsigned i = 0; i < services.size(); i++) {
120 String16 name = services[i];
121 sp<IBinder> service = sm->checkService(name);
122 aout << i
123 << "\t" << good_old_string(name)
124 << ": [" << good_old_string(get_interface_name(service)) << "]"
125 << endl;
126 }
127 } else if (strcmp(argv[optind], "call") == 0) {
128 optind++;
129 if (optind+1 < argc) {
130 int serviceArg = optind;
131 sp<IBinder> service = sm->checkService(String16(argv[optind++]));
132 String16 ifName = get_interface_name(service);
133 int32_t code = atoi(argv[optind++]);
Yi Kong19d5c002018-07-20 13:39:55 -0700134 if (service != nullptr && ifName.size() > 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700135 Parcel data, reply;
136
137 // the interface name is first
138 data.writeInterfaceToken(ifName);
139
140 // then the rest of the call arguments
141 while (optind < argc) {
142 if (strcmp(argv[optind], "i32") == 0) {
143 optind++;
144 if (optind >= argc) {
145 aerr << "service: no integer supplied for 'i32'" << endl;
146 wantsUsage = true;
147 result = 10;
148 break;
149 }
150 data.writeInt32(atoi(argv[optind++]));
Jeff Brownd46898f2015-04-06 19:42:43 -0700151 } else if (strcmp(argv[optind], "i64") == 0) {
152 optind++;
153 if (optind >= argc) {
154 aerr << "service: no integer supplied for 'i64'" << endl;
155 wantsUsage = true;
156 result = 10;
157 break;
158 }
159 data.writeInt64(atoll(argv[optind++]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700160 } else if (strcmp(argv[optind], "s16") == 0) {
161 optind++;
162 if (optind >= argc) {
163 aerr << "service: no string supplied for 's16'" << endl;
164 wantsUsage = true;
165 result = 10;
166 break;
167 }
168 data.writeString16(String16(argv[optind++]));
Jeff Brownd46898f2015-04-06 19:42:43 -0700169 } else if (strcmp(argv[optind], "f") == 0) {
170 optind++;
171 if (optind >= argc) {
172 aerr << "service: no number supplied for 'f'" << endl;
173 wantsUsage = true;
174 result = 10;
175 break;
176 }
177 data.writeFloat(atof(argv[optind++]));
178 } else if (strcmp(argv[optind], "d") == 0) {
179 optind++;
180 if (optind >= argc) {
181 aerr << "service: no number supplied for 'd'" << endl;
182 wantsUsage = true;
183 result = 10;
184 break;
185 }
186 data.writeDouble(atof(argv[optind++]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700187 } else if (strcmp(argv[optind], "null") == 0) {
188 optind++;
Yi Kong19d5c002018-07-20 13:39:55 -0700189 data.writeStrongBinder(nullptr);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700190 } else if (strcmp(argv[optind], "intent") == 0) {
191
Yi Kong19d5c002018-07-20 13:39:55 -0700192 char* action = nullptr;
193 char* dataArg = nullptr;
194 char* type = nullptr;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700195 int launchFlags = 0;
Yi Kong19d5c002018-07-20 13:39:55 -0700196 char* component = nullptr;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700197 int categoryCount = 0;
198 char* categories[16];
199
Yi Kong19d5c002018-07-20 13:39:55 -0700200 char* context1 = nullptr;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700201
202 optind++;
203
204 while (optind < argc)
205 {
206 char* key = strtok_r(argv[optind], "=", &context1);
Yi Kong19d5c002018-07-20 13:39:55 -0700207 char* value = strtok_r(nullptr, "=", &context1);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700208
209 // we have reached the end of the XXX=XXX args.
Yi Kong19d5c002018-07-20 13:39:55 -0700210 if (key == nullptr) break;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700211
212 if (strcmp(key, "action") == 0)
213 {
214 action = value;
215 }
216 else if (strcmp(key, "data") == 0)
217 {
218 dataArg = value;
219 }
220 else if (strcmp(key, "type") == 0)
221 {
222 type = value;
223 }
224 else if (strcmp(key, "launchFlags") == 0)
225 {
226 launchFlags = atoi(value);
227 }
228 else if (strcmp(key, "component") == 0)
229 {
230 component = value;
231 }
232 else if (strcmp(key, "categories") == 0)
233 {
Yi Kong19d5c002018-07-20 13:39:55 -0700234 char* context2 = nullptr;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700235 int categoryCount = 0;
236 categories[categoryCount] = strtok_r(value, ",", &context2);
237
Yi Kong19d5c002018-07-20 13:39:55 -0700238 while (categories[categoryCount] != nullptr)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700239 {
240 categoryCount++;
Yi Kong19d5c002018-07-20 13:39:55 -0700241 categories[categoryCount] = strtok_r(nullptr, ",", &context2);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700242 }
243 }
244
245 optind++;
246 }
247
248 writeString16(data, action);
249 writeString16(data, dataArg);
250 writeString16(data, type);
251 data.writeInt32(launchFlags);
252 writeString16(data, component);
253
254 if (categoryCount > 0)
255 {
256 data.writeInt32(categoryCount);
257 for (int i = 0 ; i < categoryCount ; i++)
258 {
259 writeString16(data, categories[i]);
260 }
261 }
262 else
263 {
264 data.writeInt32(0);
265 }
266
267 // for now just set the extra field to be null.
268 data.writeInt32(-1);
269 } else {
270 aerr << "service: unknown option " << argv[optind] << endl;
271 wantsUsage = true;
272 result = 10;
273 break;
274 }
275 }
276
277 service->transact(code, data, &reply);
278 aout << "Result: " << reply << endl;
279 } else {
280 aerr << "service: Service " << argv[serviceArg]
281 << " does not exist" << endl;
282 result = 10;
283 }
284 } else {
285 if (optind < argc) {
286 aerr << "service: No service specified for call" << endl;
287 } else {
288 aerr << "service: No code specified for call" << endl;
289 }
290 wantsUsage = true;
291 result = 10;
292 }
293 } else {
294 aerr << "service: Unknown command " << argv[optind] << endl;
295 wantsUsage = true;
296 result = 10;
297 }
298 }
299
300 if (wantsUsage) {
301 aout << "Usage: service [-h|-?]\n"
302 " service list\n"
303 " service check SERVICE\n"
Jeff Brownd46898f2015-04-06 19:42:43 -0700304 " service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...\n"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700305 "Options:\n"
Jeff Brownd46898f2015-04-06 19:42:43 -0700306 " i32: Write the 32-bit integer N into the send parcel.\n"
307 " i64: Write the 64-bit integer N into the send parcel.\n"
308 " f: Write the 32-bit single-precision number N into the send parcel.\n"
309 " d: Write the 64-bit double-precision number N into the send parcel.\n"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700310 " s16: Write the UTF-16 string STR into the send parcel.\n";
311// " intent: Write and Intent int the send parcel. ARGS can be\n"
312// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
313 return result;
314 }
315
316 return result;
317}
318