blob: d5ca725eb9cccb656deefaa82d47d0e111b542e0 [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>
Colin Cross6d5ef672021-12-20 17:10:16 -080024#include <libgen.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070025#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28#include <unistd.h>
Marco Nelissenb9ec70e2018-06-07 11:31:03 -070029#include <sys/mman.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070030#include <sys/time.h>
Marco Nelissenb9ec70e2018-06-07 11:31:03 -070031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070034
35using namespace android;
36
37void writeString16(Parcel& parcel, const char* string)
38{
Yi Kong19d5c002018-07-20 13:39:55 -070039 if (string != nullptr)
Mike Lockwood94afecf2012-10-24 10:45:23 -070040 {
41 parcel.writeString16(String16(string));
42 }
43 else
44 {
45 parcel.writeInt32(-1);
46 }
47}
48
Mike Lockwood94afecf2012-10-24 10:45:23 -070049int main(int argc, char* const argv[])
50{
Mike Lockwood94afecf2012-10-24 10:45:23 -070051 bool wantsUsage = false;
52 int result = 0;
Marco Nelissen07e95a82019-07-16 08:50:21 -070053
Tony Guo51cbe7e2021-10-15 14:00:07 +080054 /* Strip path off the program name. */
55 char* prog_name = basename(argv[0]);
56
Mike Lockwood94afecf2012-10-24 10:45:23 -070057 while (1) {
Martijn Coenen3def1f22017-04-07 10:46:57 -070058 int ic = getopt(argc, argv, "h?");
Mike Lockwood94afecf2012-10-24 10:45:23 -070059 if (ic < 0)
60 break;
61
62 switch (ic) {
63 case 'h':
64 case '?':
65 wantsUsage = true;
66 break;
67 default:
Tony Guo51cbe7e2021-10-15 14:00:07 +080068 aerr << prog_name << ": Unknown option -" << ic << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -070069 wantsUsage = true;
70 result = 10;
71 break;
72 }
73 }
Martijn Coenen3def1f22017-04-07 10:46:57 -070074#ifdef VENDORSERVICES
75 ProcessState::initWithDriver("/dev/vndbinder");
76#endif
Yifan Hong86cf0532021-06-16 22:56:50 -070077#ifndef __ANDROID__
78 setDefaultServiceManager(createRpcDelegateServiceManager({.maxOutgoingThreads = 1}));
79#endif
Martijn Coenend6480ca2017-04-05 14:16:12 -070080 sp<IServiceManager> sm = defaultServiceManager();
81 fflush(stdout);
Yi Kong19d5c002018-07-20 13:39:55 -070082 if (sm == nullptr) {
Tony Guo51cbe7e2021-10-15 14:00:07 +080083 aerr << prog_name << ": Unable to get default service manager!" << endl;
Martijn Coenend6480ca2017-04-05 14:16:12 -070084 return 20;
85 }
Marco Nelissen07e95a82019-07-16 08:50:21 -070086
Mike Lockwood94afecf2012-10-24 10:45:23 -070087 if (optind >= argc) {
88 wantsUsage = true;
89 } else if (!wantsUsage) {
90 if (strcmp(argv[optind], "check") == 0) {
91 optind++;
92 if (optind < argc) {
93 sp<IBinder> service = sm->checkService(String16(argv[optind]));
94 aout << "Service " << argv[optind] <<
Yi Kong19d5c002018-07-20 13:39:55 -070095 (service == nullptr ? ": not found" : ": found") << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -070096 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +080097 aerr << prog_name << ": No service specified for check" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -070098 wantsUsage = true;
99 result = 10;
100 }
101 }
102 else if (strcmp(argv[optind], "list") == 0) {
103 Vector<String16> services = sm->listServices();
104 aout << "Found " << services.size() << " services:" << endl;
105 for (unsigned i = 0; i < services.size(); i++) {
106 String16 name = services[i];
107 sp<IBinder> service = sm->checkService(name);
Marco Nelissen07e95a82019-07-16 08:50:21 -0700108 aout << i
Steven Moreland619b9352021-10-28 15:54:59 -0700109 << "\t" << name
110 << ": [" << (service ? service->getInterfaceDescriptor() : String16()) << "]"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700111 << endl;
112 }
113 } else if (strcmp(argv[optind], "call") == 0) {
114 optind++;
115 if (optind+1 < argc) {
116 int serviceArg = optind;
117 sp<IBinder> service = sm->checkService(String16(argv[optind++]));
Steven Moreland619b9352021-10-28 15:54:59 -0700118 String16 ifName = (service ? service->getInterfaceDescriptor() : String16());
Mike Lockwood94afecf2012-10-24 10:45:23 -0700119 int32_t code = atoi(argv[optind++]);
Yi Kong19d5c002018-07-20 13:39:55 -0700120 if (service != nullptr && ifName.size() > 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700121 Parcel data, reply;
Yifan Hong86cf0532021-06-16 22:56:50 -0700122 data.markForBinder(service);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700123
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) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800132 aerr << prog_name << ": no integer supplied for 'i32'" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700133 wantsUsage = true;
134 result = 10;
135 break;
136 }
137 data.writeInt32(atoi(argv[optind++]));
Jeff Brownd46898f2015-04-06 19:42:43 -0700138 } else if (strcmp(argv[optind], "i64") == 0) {
139 optind++;
140 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800141 aerr << prog_name << ": no integer supplied for 'i64'" << endl;
Jeff Brownd46898f2015-04-06 19:42:43 -0700142 wantsUsage = true;
143 result = 10;
144 break;
145 }
146 data.writeInt64(atoll(argv[optind++]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700147 } else if (strcmp(argv[optind], "s16") == 0) {
148 optind++;
149 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800150 aerr << prog_name << ": no string supplied for 's16'" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700151 wantsUsage = true;
152 result = 10;
153 break;
154 }
155 data.writeString16(String16(argv[optind++]));
Jeff Brownd46898f2015-04-06 19:42:43 -0700156 } else if (strcmp(argv[optind], "f") == 0) {
157 optind++;
158 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800159 aerr << prog_name << ": no number supplied for 'f'" << endl;
Jeff Brownd46898f2015-04-06 19:42:43 -0700160 wantsUsage = true;
161 result = 10;
162 break;
163 }
164 data.writeFloat(atof(argv[optind++]));
165 } else if (strcmp(argv[optind], "d") == 0) {
166 optind++;
167 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800168 aerr << prog_name << ": no number supplied for 'd'" << endl;
Jeff Brownd46898f2015-04-06 19:42:43 -0700169 wantsUsage = true;
170 result = 10;
171 break;
172 }
173 data.writeDouble(atof(argv[optind++]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700174 } else if (strcmp(argv[optind], "null") == 0) {
175 optind++;
Yi Kong19d5c002018-07-20 13:39:55 -0700176 data.writeStrongBinder(nullptr);
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700177 } else if (strcmp(argv[optind], "fd") == 0) {
178 optind++;
179 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800180 aerr << prog_name << ": no path supplied for 'fd'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700181 wantsUsage = true;
182 result = 10;
183 break;
184 }
185 const char *path = argv[optind++];
186 int fd = open(path, O_RDONLY);
187 if (fd < 0) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800188 aerr << prog_name << ": could not open '" << path << "'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700189 wantsUsage = true;
190 result = 10;
191 break;
192 }
193 data.writeFileDescriptor(fd, true /* take ownership */);
194 } else if (strcmp(argv[optind], "afd") == 0) {
195 optind++;
196 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800197 aerr << prog_name << ": no path supplied for 'afd'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700198 wantsUsage = true;
199 result = 10;
200 break;
201 }
202 const char *path = argv[optind++];
203 int fd = open(path, O_RDONLY);
204 struct stat statbuf;
205 if (fd < 0 || fstat(fd, &statbuf) != 0) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800206 aerr << prog_name << ": could not open or stat"
207 << " '" << path << "'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700208 wantsUsage = true;
209 result = 10;
210 break;
211 }
212 int afd = ashmem_create_region("test", statbuf.st_size);
213 void* ptr = mmap(NULL, statbuf.st_size,
214 PROT_READ | PROT_WRITE, MAP_SHARED, afd, 0);
Yifan Hong86cf0532021-06-16 22:56:50 -0700215 (void)read(fd, ptr, statbuf.st_size);
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700216 close(fd);
217 data.writeFileDescriptor(afd, true /* take ownership */);
218 } else if (strcmp(argv[optind], "nfd") == 0) {
219 optind++;
220 if (optind >= argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800221 aerr << prog_name << ": no file descriptor supplied for"
222 << " 'nfd'" << endl;
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700223 wantsUsage = true;
224 result = 10;
225 break;
226 }
227 data.writeFileDescriptor(
228 atoi(argv[optind++]), true /* take ownership */);
229
Mike Lockwood94afecf2012-10-24 10:45:23 -0700230 } else if (strcmp(argv[optind], "intent") == 0) {
Marco Nelissen07e95a82019-07-16 08:50:21 -0700231
232 char* action = nullptr;
233 char* dataArg = nullptr;
234 char* type = nullptr;
235 int launchFlags = 0;
236 char* component = nullptr;
237 int categoryCount = 0;
238 char* categories[16];
239
240 char* context1 = nullptr;
241
Mike Lockwood94afecf2012-10-24 10:45:23 -0700242 optind++;
Marco Nelissen07e95a82019-07-16 08:50:21 -0700243
244 while (optind < argc)
245 {
246 char* key = strtok_r(argv[optind], "=", &context1);
247 char* value = strtok_r(nullptr, "=", &context1);
248
Mike Lockwood94afecf2012-10-24 10:45:23 -0700249 // we have reached the end of the XXX=XXX args.
Yi Kong19d5c002018-07-20 13:39:55 -0700250 if (key == nullptr) break;
Marco Nelissen07e95a82019-07-16 08:50:21 -0700251
252 if (strcmp(key, "action") == 0)
253 {
254 action = value;
255 }
256 else if (strcmp(key, "data") == 0)
257 {
258 dataArg = value;
259 }
260 else if (strcmp(key, "type") == 0)
261 {
262 type = value;
263 }
264 else if (strcmp(key, "launchFlags") == 0)
265 {
266 launchFlags = atoi(value);
267 }
268 else if (strcmp(key, "component") == 0)
269 {
270 component = value;
271 }
272 else if (strcmp(key, "categories") == 0)
273 {
274 char* context2 = nullptr;
Marco Nelissen07e95a82019-07-16 08:50:21 -0700275 categories[categoryCount] = strtok_r(value, ",", &context2);
276
277 while (categories[categoryCount] != nullptr)
278 {
279 categoryCount++;
280 categories[categoryCount] = strtok_r(nullptr, ",", &context2);
281 }
282 }
283
Mike Lockwood94afecf2012-10-24 10:45:23 -0700284 optind++;
Marco Nelissen07e95a82019-07-16 08:50:21 -0700285 }
286
Mike Lockwood94afecf2012-10-24 10:45:23 -0700287 writeString16(data, action);
288 writeString16(data, dataArg);
289 writeString16(data, type);
Marco Nelissen07e95a82019-07-16 08:50:21 -0700290 data.writeInt32(launchFlags);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700291 writeString16(data, component);
Marco Nelissen07e95a82019-07-16 08:50:21 -0700292
Mike Lockwood94afecf2012-10-24 10:45:23 -0700293 if (categoryCount > 0)
294 {
295 data.writeInt32(categoryCount);
296 for (int i = 0 ; i < categoryCount ; i++)
297 {
298 writeString16(data, categories[i]);
299 }
300 }
301 else
302 {
303 data.writeInt32(0);
Marco Nelissen07e95a82019-07-16 08:50:21 -0700304 }
305
Mike Lockwood94afecf2012-10-24 10:45:23 -0700306 // for now just set the extra field to be null.
Marco Nelissen07e95a82019-07-16 08:50:21 -0700307 data.writeInt32(-1);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700308 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800309 aerr << prog_name << ": unknown option " << argv[optind] << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700310 wantsUsage = true;
311 result = 10;
312 break;
313 }
314 }
Marco Nelissen07e95a82019-07-16 08:50:21 -0700315
Mike Lockwood94afecf2012-10-24 10:45:23 -0700316 service->transact(code, data, &reply);
317 aout << "Result: " << reply << endl;
318 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800319 aerr << prog_name << ": Service " << argv[serviceArg]
Mike Lockwood94afecf2012-10-24 10:45:23 -0700320 << " does not exist" << endl;
321 result = 10;
322 }
323 } else {
324 if (optind < argc) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800325 aerr << prog_name << ": No service specified for call" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700326 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800327 aerr << prog_name << ": No code specified for call" << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700328 }
329 wantsUsage = true;
330 result = 10;
331 }
332 } else {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800333 aerr << prog_name << ": Unknown command " << argv[optind] << endl;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700334 wantsUsage = true;
335 result = 10;
336 }
337 }
Marco Nelissen07e95a82019-07-16 08:50:21 -0700338
Mike Lockwood94afecf2012-10-24 10:45:23 -0700339 if (wantsUsage) {
Tony Guo51cbe7e2021-10-15 14:00:07 +0800340 aout << "Usage: " << prog_name << " [-h|-?]\n"
341 " " << prog_name << " list\n"
342 " " << prog_name << " check SERVICE\n"
343 " " << prog_name << " call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR"
344 " | null | fd f | nfd n | afd f ] ...\n"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700345 "Options:\n"
Jeff Brownd46898f2015-04-06 19:42:43 -0700346 " i32: Write the 32-bit integer N into the send parcel.\n"
347 " i64: Write the 64-bit integer N into the send parcel.\n"
Tony Guo51cbe7e2021-10-15 14:00:07 +0800348 " f: Write the 32-bit single-precision number N into the send parcel.\n"
349 " d: Write the 64-bit double-precision number N into the send parcel.\n"
Marco Nelissenb9ec70e2018-06-07 11:31:03 -0700350 " s16: Write the UTF-16 string STR into the send parcel.\n"
351 " null: Write a null binder into the send parcel.\n"
Tony Guo51cbe7e2021-10-15 14:00:07 +0800352 " fd: Write a file descriptor for the file f into the send parcel.\n"
353 " nfd: Write the file descriptor n into the send parcel.\n"
354 " afd: Write an ashmem file descriptor for a region containing the data from\n"
355 " file f into the send parcel.\n";
356// " intent: Write an Intent into the send parcel. ARGS can be\n"
Mike Lockwood94afecf2012-10-24 10:45:23 -0700357// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
358 return result;
359 }
Marco Nelissen07e95a82019-07-16 08:50:21 -0700360
Mike Lockwood94afecf2012-10-24 10:45:23 -0700361 return result;
362}
363