• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 The Android Open Source Project
3  *
4  * 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.
15  */
16 
17 #include <binder/Parcel.h>
18 #include <binder/ProcessState.h>
19 #include <binder/IServiceManager.h>
20 #include <binder/TextOutput.h>
21 
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 
29 using namespace android;
30 
writeString16(Parcel & parcel,const char * string)31 void 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
get_interface_name(sp<IBinder> service)44 static 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 
good_old_string(const String16 & src)56 static 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 
main(int argc,char * const argv[])69 int main(int argc, char* const argv[])
70 {
71     bool wantsUsage = false;
72     int result = 0;
73 
74     while (1) {
75         int ic = getopt(argc, argv, "h?");
76         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     }
91 #ifdef VENDORSERVICES
92     ProcessState::initWithDriver("/dev/vndbinder");
93 #endif
94     sp<IServiceManager> sm = defaultServiceManager();
95     fflush(stdout);
96     if (sm == NULL) {
97         aerr << "service: Unable to get default service manager!" << endl;
98         return 20;
99     }
100 
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] <<
109                     (service == NULL ? ": not found" : ": found") << endl;
110             } 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++]);
134                 if (service != NULL && ifName.size() > 0) {
135                     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++]));
151                         } 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++]));
160                         } 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++]));
169                         } 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++]));
187                         } else if (strcmp(argv[optind], "null") == 0) {
188                             optind++;
189                             data.writeStrongBinder(NULL);
190                         } else if (strcmp(argv[optind], "intent") == 0) {
191 
192                         	char* action = NULL;
193                         	char* dataArg = NULL;
194                         	char* type = NULL;
195                         	int launchFlags = 0;
196                         	char* component = NULL;
197                         	int categoryCount = 0;
198                         	char* categories[16];
199 
200                         	char* context1 = NULL;
201 
202                             optind++;
203 
204                         	while (optind < argc)
205                         	{
206                         		char* key = strtok_r(argv[optind], "=", &context1);
207                         		char* value = strtok_r(NULL, "=", &context1);
208 
209                                 // we have reached the end of the XXX=XXX args.
210                                 if (key == NULL) break;
211 
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                         		{
234                         			char* context2 = NULL;
235                         			int categoryCount = 0;
236                         			categories[categoryCount] = strtok_r(value, ",", &context2);
237 
238                         			while (categories[categoryCount] != NULL)
239                         			{
240                         				categoryCount++;
241                         				categories[categoryCount] = strtok_r(NULL, ",", &context2);
242                         			}
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"
304                 "       service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...\n"
305                 "Options:\n"
306                 "   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"
310                 "   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 
319