blob: 97fc47c544fc97497d1ad67571991eb3e8dc463b [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++]));
149 } else if (strcmp(argv[optind], "s16") == 0) {
150 optind++;
151 if (optind >= argc) {
152 aerr << "service: no string supplied for 's16'" << endl;
153 wantsUsage = true;
154 result = 10;
155 break;
156 }
157 data.writeString16(String16(argv[optind++]));
158 } else if (strcmp(argv[optind], "null") == 0) {
159 optind++;
160 data.writeStrongBinder(NULL);
161 } else if (strcmp(argv[optind], "intent") == 0) {
162
163 char* action = NULL;
164 char* dataArg = NULL;
165 char* type = NULL;
166 int launchFlags = 0;
167 char* component = NULL;
168 int categoryCount = 0;
169 char* categories[16];
170
171 char* context1 = NULL;
172
173 optind++;
174
175 while (optind < argc)
176 {
177 char* key = strtok_r(argv[optind], "=", &context1);
178 char* value = strtok_r(NULL, "=", &context1);
179
180 // we have reached the end of the XXX=XXX args.
181 if (key == NULL) break;
182
183 if (strcmp(key, "action") == 0)
184 {
185 action = value;
186 }
187 else if (strcmp(key, "data") == 0)
188 {
189 dataArg = value;
190 }
191 else if (strcmp(key, "type") == 0)
192 {
193 type = value;
194 }
195 else if (strcmp(key, "launchFlags") == 0)
196 {
197 launchFlags = atoi(value);
198 }
199 else if (strcmp(key, "component") == 0)
200 {
201 component = value;
202 }
203 else if (strcmp(key, "categories") == 0)
204 {
205 char* context2 = NULL;
206 int categoryCount = 0;
207 categories[categoryCount] = strtok_r(value, ",", &context2);
208
209 while (categories[categoryCount] != NULL)
210 {
211 categoryCount++;
212 categories[categoryCount] = strtok_r(NULL, ",", &context2);
213 }
214 }
215
216 optind++;
217 }
218
219 writeString16(data, action);
220 writeString16(data, dataArg);
221 writeString16(data, type);
222 data.writeInt32(launchFlags);
223 writeString16(data, component);
224
225 if (categoryCount > 0)
226 {
227 data.writeInt32(categoryCount);
228 for (int i = 0 ; i < categoryCount ; i++)
229 {
230 writeString16(data, categories[i]);
231 }
232 }
233 else
234 {
235 data.writeInt32(0);
236 }
237
238 // for now just set the extra field to be null.
239 data.writeInt32(-1);
240 } else {
241 aerr << "service: unknown option " << argv[optind] << endl;
242 wantsUsage = true;
243 result = 10;
244 break;
245 }
246 }
247
248 service->transact(code, data, &reply);
249 aout << "Result: " << reply << endl;
250 } else {
251 aerr << "service: Service " << argv[serviceArg]
252 << " does not exist" << endl;
253 result = 10;
254 }
255 } else {
256 if (optind < argc) {
257 aerr << "service: No service specified for call" << endl;
258 } else {
259 aerr << "service: No code specified for call" << endl;
260 }
261 wantsUsage = true;
262 result = 10;
263 }
264 } else {
265 aerr << "service: Unknown command " << argv[optind] << endl;
266 wantsUsage = true;
267 result = 10;
268 }
269 }
270
271 if (wantsUsage) {
272 aout << "Usage: service [-h|-?]\n"
273 " service list\n"
274 " service check SERVICE\n"
275 " service call SERVICE CODE [i32 INT | s16 STR] ...\n"
276 "Options:\n"
277 " i32: Write the integer INT into the send parcel.\n"
278 " s16: Write the UTF-16 string STR into the send parcel.\n";
279// " intent: Write and Intent int the send parcel. ARGS can be\n"
280// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
281 return result;
282 }
283
284 return result;
285}
286