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