Home | History | Annotate | Download | only in service
      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 
     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
     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 
     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 
     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