• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Command line access to services.
3  *
4  */
5 
6 #include <binder/Parcel.h>
7 #include <binder/ProcessState.h>
8 #include <binder/IServiceManager.h>
9 #include <utils/TextOutput.h>
10 
11 #include <getopt.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <sys/time.h>
17 
18 using namespace android;
19 
writeString16(Parcel & parcel,const char * string)20 void writeString16(Parcel& parcel, const char* string)
21 {
22     if (string != NULL)
23     {
24         parcel.writeString16(String16(string));
25     }
26     else
27     {
28         parcel.writeInt32(-1);
29     }
30 }
31 
32 // get the name of the generic interface we hold a reference to
get_interface_name(sp<IBinder> service)33 static String16 get_interface_name(sp<IBinder> service)
34 {
35     if (service != NULL) {
36         Parcel data, reply;
37         status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);
38         if (err == NO_ERROR) {
39             return reply.readString16();
40         }
41     }
42     return String16();
43 }
44 
good_old_string(const String16 & src)45 static String8 good_old_string(const String16& src)
46 {
47     String8 name8;
48     char ch8[2];
49     ch8[1] = 0;
50     for (unsigned j = 0; j < src.size(); j++) {
51         char16_t ch = src[j];
52         if (ch < 128) ch8[0] = (char)ch;
53         name8.append(ch8);
54     }
55     return name8;
56 }
57 
main(int argc,char * const argv[])58 int main(int argc, char* const argv[])
59 {
60     sp<IServiceManager> sm = defaultServiceManager();
61     fflush(stdout);
62     if (sm == NULL) {
63         aerr << "service: Unable to get default service manager!" << endl;
64         return 20;
65     }
66 
67     bool wantsUsage = false;
68     int result = 0;
69 
70     while (1) {
71         int ic = getopt(argc, argv, "h?");
72         if (ic < 0)
73             break;
74 
75         switch (ic) {
76         case 'h':
77         case '?':
78             wantsUsage = true;
79             break;
80         default:
81             aerr << "service: Unknown option -" << ic << endl;
82             wantsUsage = true;
83             result = 10;
84             break;
85         }
86     }
87 
88     if (optind >= argc) {
89         wantsUsage = true;
90     } else if (!wantsUsage) {
91         if (strcmp(argv[optind], "check") == 0) {
92             optind++;
93             if (optind < argc) {
94                 sp<IBinder> service = sm->checkService(String16(argv[optind]));
95                 aout << "Service " << argv[optind] <<
96                     (service == NULL ? ": not found" : ": found") << endl;
97             } else {
98                 aerr << "service: No service specified for check" << endl;
99                 wantsUsage = true;
100                 result = 10;
101             }
102         }
103         else if (strcmp(argv[optind], "list") == 0) {
104             Vector<String16> services = sm->listServices();
105             aout << "Found " << services.size() << " services:" << endl;
106             for (unsigned i = 0; i < services.size(); i++) {
107                 String16 name = services[i];
108                 sp<IBinder> service = sm->checkService(name);
109                 aout << i
110                      << "\t" << good_old_string(name)
111                      << ": [" << good_old_string(get_interface_name(service)) << "]"
112                      << endl;
113             }
114         } else if (strcmp(argv[optind], "call") == 0) {
115             optind++;
116             if (optind+1 < argc) {
117                 int serviceArg = optind;
118                 sp<IBinder> service = sm->checkService(String16(argv[optind++]));
119                 String16 ifName = get_interface_name(service);
120                 int32_t code = atoi(argv[optind++]);
121                 if (service != NULL && ifName.size() > 0) {
122                     Parcel data, reply;
123 
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) {
132                                 aerr << "service: no integer supplied for 'i32'" << endl;
133                                 wantsUsage = true;
134                                 result = 10;
135                                 break;
136                             }
137                             data.writeInt32(atoi(argv[optind++]));
138                         } else if (strcmp(argv[optind], "s16") == 0) {
139                             optind++;
140                             if (optind >= argc) {
141                                 aerr << "service: no string supplied for 's16'" << endl;
142                                 wantsUsage = true;
143                                 result = 10;
144                                 break;
145                             }
146                             data.writeString16(String16(argv[optind++]));
147                         } else if (strcmp(argv[optind], "null") == 0) {
148                             optind++;
149                             data.writeStrongBinder(NULL);
150                         } else if (strcmp(argv[optind], "intent") == 0) {
151 
152                         	char* action = NULL;
153                         	char* dataArg = NULL;
154                         	char* type = NULL;
155                         	int launchFlags = 0;
156                         	char* component = NULL;
157                         	int categoryCount = 0;
158                         	char* categories[16];
159 
160                         	char* context1 = NULL;
161 
162                             optind++;
163 
164                         	while (optind < argc)
165                         	{
166                         		char* key = strtok_r(argv[optind], "=", &context1);
167                         		char* value = strtok_r(NULL, "=", &context1);
168 
169                                 // we have reached the end of the XXX=XXX args.
170                                 if (key == NULL) break;
171 
172                         		if (strcmp(key, "action") == 0)
173                         		{
174                         			action = value;
175                         		}
176                         		else if (strcmp(key, "data") == 0)
177                         		{
178                         			dataArg = value;
179                         		}
180                         		else if (strcmp(key, "type") == 0)
181                         		{
182                         			type = value;
183                         		}
184                         		else if (strcmp(key, "launchFlags") == 0)
185                         		{
186                         			launchFlags = atoi(value);
187                         		}
188                         		else if (strcmp(key, "component") == 0)
189                         		{
190                         			component = value;
191                         		}
192                         		else if (strcmp(key, "categories") == 0)
193                         		{
194                         			char* context2 = NULL;
195                         			int categoryCount = 0;
196                         			categories[categoryCount] = strtok_r(value, ",", &context2);
197 
198                         			while (categories[categoryCount] != NULL)
199                         			{
200                         				categoryCount++;
201                         				categories[categoryCount] = strtok_r(NULL, ",", &context2);
202                         			}
203                         		}
204 
205                                 optind++;
206                         	}
207 
208                             writeString16(data, action);
209                             writeString16(data, dataArg);
210                             writeString16(data, type);
211                        		data.writeInt32(launchFlags);
212                             writeString16(data, component);
213 
214                             if (categoryCount > 0)
215                             {
216                                 data.writeInt32(categoryCount);
217                                 for (int i = 0 ; i < categoryCount ; i++)
218                                 {
219                                     writeString16(data, categories[i]);
220                                 }
221                             }
222                             else
223                             {
224                                 data.writeInt32(0);
225                             }
226 
227                             // for now just set the extra field to be null.
228                        		data.writeInt32(-1);
229                         } else {
230                             aerr << "service: unknown option " << argv[optind] << endl;
231                             wantsUsage = true;
232                             result = 10;
233                             break;
234                         }
235                     }
236 
237                     service->transact(code, data, &reply);
238                     aout << "Result: " << reply << endl;
239                 } else {
240                     aerr << "service: Service " << argv[serviceArg]
241                         << " does not exist" << endl;
242                     result = 10;
243                 }
244             } else {
245                 if (optind < argc) {
246                     aerr << "service: No service specified for call" << endl;
247                 } else {
248                     aerr << "service: No code specified for call" << endl;
249                 }
250                 wantsUsage = true;
251                 result = 10;
252             }
253         } else {
254             aerr << "service: Unknown command " << argv[optind] << endl;
255             wantsUsage = true;
256             result = 10;
257         }
258     }
259 
260     if (wantsUsage) {
261         aout << "Usage: service [-h|-?]\n"
262                 "       service list\n"
263                 "       service check SERVICE\n"
264                 "       service call SERVICE CODE [i32 INT | s16 STR] ...\n"
265                 "Options:\n"
266                 "   i32: Write the integer INT into the send parcel.\n"
267                 "   s16: Write the UTF-16 string STR into the send parcel.\n";
268 //                "   intent: Write and Intent int the send parcel. ARGS can be\n"
269 //                "       action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
270         return result;
271     }
272 
273     return result;
274 }
275 
276