• 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