blob: fe417a362f547e1e7f98a6f12315db42bb17d865 [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>
Marco Nelissenb9ec70e2018-06-07 11:31:03 -070021#include <cutils/ashmem.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070022
23#include <getopt.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <unistd.h>
Marco Nelissenb9ec70e2018-06-07 11:31:03 -070028#include <sys/mman.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070029#include <sys/time.h>
Marco Nelissenb9ec70e2018-06-07 11:31:03 -070030#include <sys/types.h>
31#include <sys/stat.h>
32#include <fcntl.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070033
34using namespace android;
35
36void writeString16(Parcel& parcel, const char* string)
37{
Yi Kong19d5c002018-07-20 13:39:55 -070038 if (string != nullptr)
Mike Lockwood94afecf2012-10-24 10:45:23 -070039 {
40 parcel.writeString16(String16(string));
41 }
42 else
43 {
44 parcel.writeInt32(-1);
45 }
46}
47
Mike Lockwood94afecf2012-10-24 10:45:23 -070048int main(int argc, char* const argv[])
49{
Mike Lockwood94afecf2012-10-24 10:45:23 -070050 bool wantsUsage = false;
51 int result = 0;
Marco Nelissen07e95a82019-07-16 08:50:21 -070052
Tony Guo51cbe7e2021-10-15 14:00:07 +080053 /* Strip path off the program name. */
54 char* prog_name = basename(argv[0]);
55
Mike Lockwood94afecf2012-10-24 10:45:23 -070056 while (1) {
Martijn Coenen3def1f22017-04-07 10:46:57 -070057 int ic = getopt(argc, argv, "h?");
Mike Lockwood94afecf2012-10-24 10:45:23 -070058 if (ic < 0)
59 break;
60
61 switch (ic) {
62 case 'h':
63 case '?':
64 wantsUsage = true;
65 break;
66 default:
Tony Guo51cbe7e2021-10-15 14:00:07 +080067 aerr << prog_name << ": Unknown option -" << ic << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -070068 wantsUsage = true;
69 result = 10;
70 break;
71 }
72 }
Martijn Coenen3def1f22017-04-07 10:46:57 -070073#ifdef VENDORSERVICES
74 ProcessState::initWithDriver("/dev/vndbinder");
75#endif
Yifan Hong86cf0532021-06-16 22:56:50 -070076#ifndef __ANDROID__
77 setDefaultServiceManager(createRpcDelegateServiceManager({.maxOutgoingThreads = 1}));
78#endif
Martijn Coenend6480ca2017-04-05 14:16:12 -070079 sp<IServiceManager> sm = defaultServiceManager();
80 fflush(stdout);
Yi Kong19d5c002018-07-20 13:39:55 -070081 if (sm == nullptr) {
Tony Guo51cbe7e2021-10-15 14:00:07 +080082 aerr << prog_name << ": Unable to get default service manager!" << endl;
Martijn Coenend6480ca2017-04-05 14:16:12 -070083 return 20;
84 }
Marco Nelissen07e95a82019-07-16 08:50:21 -070085
Mike Lockwood94afecf2012-10-24 10:45:23 -070086 if (optind >= argc) {
87 wantsUsage = true;
88 } else if (!wantsUsage) {
89 if (strcmp(argv[optind], "check") == 0) {
90 optind++;
91 if (optind < argc) {
92 sp<IBinder> service = sm->checkService(String16(argv[optind]));
93 aout << "Service " << argv[optind] <<
Yi Kong19d5c002018-07-20 13:39:55 -070094 (service == nullptr ? ": not found" : ": found") << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -070095 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +080096 aerr << prog_name << ": No service specified for check" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -070097 wantsUsage = true;
98 result = 10;
99 }
100 }
101 else if (strcmp(argv[optind], "list") == 0) {
102 Vector<String16> services = sm->listServices();
103 aout << "Found " << services.size() << " services:" << endl;
104 for (unsigned i = 0; i < services.size(); i++) {
105 String16 name = services[i];
106 sp<IBinder> service = sm->checkService(name);
Marco Nelissen07e95a82019-07-16 08:50:21 -0700107 aout << i
Steven Moreland619b9352021-10-28 15:54:59 -0700108 << "\t" << name
109 << ": [" << (service ? service->getInterfaceDescriptor() : String16()) << "]"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700110 << endl;
111 }
112 } else if (strcmp(argv[optind], "call") == 0) {
113 optind++;
114 if (optind+1 < argc) {
115 int serviceArg = optind;
116 sp<IBinder> service = sm->checkService(String16(argv[optind++]));
Steven Moreland619b9352021-10-28 15:54:59 -0700117 String16 ifName = (service ? service->getInterfaceDescriptor() : String16());
Mike Lockwood94afecf2012-10-24 10:45:23 -0700118 int32_t code = atoi(argv[optind++]);
Yi Kong19d5c002018-07-20 13:39:55 -0700119 if (service != nullptr && ifName.size() > 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700120 Parcel data, reply;
Yifan Hong86cf0532021-06-16 22:56:50 -0700121 data.markForBinder(service);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700122
123 // the interface name is first
124 data.writeInterfaceToken(ifName);
125
126 // then the rest of the call arguments
127 while (optind < argc) {
128 if (strcmp(argv[optind], "i32") == 0) {
129 optind++;
130 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800131 aerr << prog_name << ": no integer supplied for 'i32'" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700132 wantsUsage = true;
133 result = 10;
134 break;
135 }
136 data.writeInt32(atoi(argv[optind++]));
Jeff Brownd46898f2015-04-06 19:42:43 -0700137 } else if (strcmp(argv[optind], "i64") == 0) {
138 optind++;
139 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800140 aerr << prog_name << ": no integer supplied for 'i64'" << endl;
Jeff Brownd46898f2015-04-06 19:42:43 -0700141 wantsUsage = true;
142 result = 10;
143 break;
144 }
145 data.writeInt64(atoll(argv[optind++]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700146 } else if (strcmp(argv[optind], "s16") == 0) {
147 optind++;
148 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800149 aerr << prog_name << ": no string supplied for 's16'" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700150 wantsUsage = true;
151 result = 10;
152 break;
153 }
154 data.writeString16(String16(argv[optind++]));
Jeff Brownd46898f2015-04-06 19:42:43 -0700155 } else if (strcmp(argv[optind], "f") == 0) {
156 optind++;
157 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800158 aerr << prog_name << ": no number supplied for 'f'" << endl;
Jeff Brownd46898f2015-04-06 19:42:43 -0700159 wantsUsage = true;
160 result = 10;
161 break;
162 }
163 data.writeFloat(atof(argv[optind++]));
164 } else if (strcmp(argv[optind], "d") == 0) {
165 optind++;
166 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800167 aerr << prog_name << ": no number supplied for 'd'" << endl;
Jeff Brownd46898f2015-04-06 19:42:43 -0700168 wantsUsage = true;
169 result = 10;
170 break;
171 }
172 data.writeDouble(atof(argv[optind++]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700173 } else if (strcmp(argv[optind], "null") == 0) {
174 optind++;
Yi Kong19d5c002018-07-20 13:39:55 -0700175 data.writeStrongBinder(nullptr);
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700176 } else if (strcmp(argv[optind], "fd") == 0) {
177 optind++;
178 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800179 aerr << prog_name << ": no path supplied for 'fd'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700180 wantsUsage = true;
181 result = 10;
182 break;
183 }
184 const char *path = argv[optind++];
185 int fd = open(path, O_RDONLY);
186 if (fd < 0) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800187 aerr << prog_name << ": could not open '" << path << "'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700188 wantsUsage = true;
189 result = 10;
190 break;
191 }
192 data.writeFileDescriptor(fd, true /* take ownership */);
193 } else if (strcmp(argv[optind], "afd") == 0) {
194 optind++;
195 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800196 aerr << prog_name << ": no path supplied for 'afd'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700197 wantsUsage = true;
198 result = 10;
199 break;
200 }
201 const char *path = argv[optind++];
202 int fd = open(path, O_RDONLY);
203 struct stat statbuf;
204 if (fd < 0 || fstat(fd, &statbuf) != 0) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800205 aerr << prog_name << ": could not open or stat"
206 << " '" << path << "'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700207 wantsUsage = true;
208 result = 10;
209 break;
210 }
211 int afd = ashmem_create_region("test", statbuf.st_size);
212 void* ptr = mmap(NULL, statbuf.st_size,
213 PROT_READ | PROT_WRITE, MAP_SHARED, afd, 0);
Yifan Hong86cf0532021-06-16 22:56:50 -0700214 (void)read(fd, ptr, statbuf.st_size);
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700215 close(fd);
216 data.writeFileDescriptor(afd, true /* take ownership */);
217 } else if (strcmp(argv[optind], "nfd") == 0) {
218 optind++;
219 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800220 aerr << prog_name << ": no file descriptor supplied for"
221 << " 'nfd'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700222 wantsUsage = true;
223 result = 10;
224 break;
225 }
226 data.writeFileDescriptor(
227 atoi(argv[optind++]), true /* take ownership */);
228
Mike Lockwood94afecf2012-10-24 10:45:23 -0700229 } else if (strcmp(argv[optind], "intent") == 0) {
Marco Nelissen07e95a82019-07-16 08:50:21 -0700230
231 char* action = nullptr;
232 char* dataArg = nullptr;
233 char* type = nullptr;
234 int launchFlags = 0;
235 char* component = nullptr;
236 int categoryCount = 0;
237 char* categories[16];
238
239 char* context1 = nullptr;
240
Mike Lockwood94afecf2012-10-24 10:45:23 -0700241 optind++;
Marco Nelissen07e95a82019-07-16 08:50:21 -0700242
243 while (optind < argc)
244 {
245 char* key = strtok_r(argv[optind], "=", &context1);
246 char* value = strtok_r(nullptr, "=", &context1);
247
Mike Lockwood94afecf2012-10-24 10:45:23 -0700248 // we have reached the end of the XXX=XXX args.
Yi Kong19d5c002018-07-20 13:39:55 -0700249 if (key == nullptr) break;
Marco Nelissen07e95a82019-07-16 08:50:21 -0700250
251 if (strcmp(key, "action") == 0)
252 {
253 action = value;
254 }
255 else if (strcmp(key, "data") == 0)
256 {
257 dataArg = value;
258 }
259 else if (strcmp(key, "type") == 0)
260 {
261 type = value;
262 }
263 else if (strcmp(key, "launchFlags") == 0)
264 {
265 launchFlags = atoi(value);
266 }
267 else if (strcmp(key, "component") == 0)
268 {
269 component = value;
270 }
271 else if (strcmp(key, "categories") == 0)
272 {
273 char* context2 = nullptr;
Marco Nelissen07e95a82019-07-16 08:50:21 -0700274 categories[categoryCount] = strtok_r(value, ",", &context2);
275
276 while (categories[categoryCount] != nullptr)
277 {
278 categoryCount++;
279 categories[categoryCount] = strtok_r(nullptr, ",", &context2);
280 }
281 }
282
Mike Lockwood94afecf2012-10-24 10:45:23 -0700283 optind++;
Marco Nelissen07e95a82019-07-16 08:50:21 -0700284 }
285
Mike Lockwood94afecf2012-10-24 10:45:23 -0700286 writeString16(data, action);
287 writeString16(data, dataArg);
288 writeString16(data, type);
Marco Nelissen07e95a82019-07-16 08:50:21 -0700289 data.writeInt32(launchFlags);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700290 writeString16(data, component);
Marco Nelissen07e95a82019-07-16 08:50:21 -0700291
Mike Lockwood94afecf2012-10-24 10:45:23 -0700292 if (categoryCount > 0)
293 {
294 data.writeInt32(categoryCount);
295 for (int i = 0 ; i < categoryCount ; i++)
296 {
297 writeString16(data, categories[i]);
298 }
299 }
300 else
301 {
302 data.writeInt32(0);
Marco Nelissen07e95a82019-07-16 08:50:21 -0700303 }
304
Mike Lockwood94afecf2012-10-24 10:45:23 -0700305 // for now just set the extra field to be null.
Marco Nelissen07e95a82019-07-16 08:50:21 -0700306 data.writeInt32(-1);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700307 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800308 aerr << prog_name << ": unknown option " << argv[optind] << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700309 wantsUsage = true;
310 result = 10;
311 break;
312 }
313 }
Marco Nelissen07e95a82019-07-16 08:50:21 -0700314
Mike Lockwood94afecf2012-10-24 10:45:23 -0700315 service->transact(code, data, &reply);
316 aout << "Result: " << reply << endl;
317 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800318 aerr << prog_name << ": Service " << argv[serviceArg]
Mike Lockwood94afecf2012-10-24 10:45:23 -0700319 << " does not exist" << endl;
320 result = 10;
321 }
322 } else {
323 if (optind < argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800324 aerr << prog_name << ": No service specified for call" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700325 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800326 aerr << prog_name << ": No code specified for call" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700327 }
328 wantsUsage = true;
329 result = 10;
330 }
331 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800332 aerr << prog_name << ": Unknown command " << argv[optind] << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700333 wantsUsage = true;
334 result = 10;
335 }
336 }
Marco Nelissen07e95a82019-07-16 08:50:21 -0700337
Mike Lockwood94afecf2012-10-24 10:45:23 -0700338 if (wantsUsage) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800339 aout << "Usage: " << prog_name << " [-h|-?]\n"
340 " " << prog_name << " list\n"
341 " " << prog_name << " check SERVICE\n"
342 " " << prog_name << " call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR"
343 " | null | fd f | nfd n | afd f ] ...\n"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700344 "Options:\n"
Jeff Brownd46898f2015-04-06 19:42:43 -0700345 " i32: Write the 32-bit integer N into the send parcel.\n"
346 " i64: Write the 64-bit integer N into the send parcel.\n"
Tony Guo51cbe7e2021-10-15 14:00:07 +0800347 " f: Write the 32-bit single-precision number N into the send parcel.\n"
348 " d: Write the 64-bit double-precision number N into the send parcel.\n"
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700349 " s16: Write the UTF-16 string STR into the send parcel.\n"
350 " null: Write a null binder into the send parcel.\n"
Tony Guo51cbe7e2021-10-15 14:00:07 +0800351 " fd: Write a file descriptor for the file f into the send parcel.\n"
352 " nfd: Write the file descriptor n into the send parcel.\n"
353 " afd: Write an ashmem file descriptor for a region containing the data from\n"
354 " file f into the send parcel.\n";
355// " intent: Write an Intent into the send parcel. ARGS can be\n"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700356// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
357 return result;
358 }
Marco Nelissen07e95a82019-07-16 08:50:21 -0700359
Mike Lockwood94afecf2012-10-24 10:45:23 -0700360 return result;
361}
362