Home | History | Annotate | Download | only in service
      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 
     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
     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 
     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 
     69 int main(int argc, char* const argv[])
     70 {
     71     sp<IServiceManager> sm = defaultServiceManager();
     72     fflush(stdout);
     73     if (sm == NULL) {
     74         aerr << "service: Unable to get default service manager!" << endl;
     75         return 20;
     76     }
     77 
     78     bool wantsUsage = false;
     79     int result = 0;
     80 
     81     while (1) {
     82         int ic = getopt(argc, argv, "h?");
     83         if (ic < 0)
     84             break;
     85 
     86         switch (ic) {
     87         case 'h':
     88         case '?':
     89             wantsUsage = true;
     90             break;
     91         default:
     92             aerr << "service: Unknown option -" << ic << endl;
     93             wantsUsage = true;
     94             result = 10;
     95             break;
     96         }
     97     }
     98 
     99     if (optind >= argc) {
    100         wantsUsage = true;
    101     } else if (!wantsUsage) {
    102         if (strcmp(argv[optind], "check") == 0) {
    103             optind++;
    104             if (optind < argc) {
    105                 sp<IBinder> service = sm->checkService(String16(argv[optind]));
    106                 aout << "Service " << argv[optind] <<
    107                     (service == NULL ? ": not found" : ": found") << endl;
    108             } else {
    109                 aerr << "service: No service specified for check" << endl;
    110                 wantsUsage = true;
    111                 result = 10;
    112             }
    113         }
    114         else if (strcmp(argv[optind], "list") == 0) {
    115             Vector<String16> services = sm->listServices();
    116             aout << "Found " << services.size() << " services:" << endl;
    117             for (unsigned i = 0; i < services.size(); i++) {
    118                 String16 name = services[i];
    119                 sp<IBinder> service = sm->checkService(name);
    120                 aout << i
    121                      << "\t" << good_old_string(name)
    122                      << ": [" << good_old_string(get_interface_name(service)) << "]"
    123                      << endl;
    124             }
    125         } else if (strcmp(argv[optind], "call") == 0) {
    126             optind++;
    127             if (optind+1 < argc) {
    128                 int serviceArg = optind;
    129                 sp<IBinder> service = sm->checkService(String16(argv[optind++]));
    130                 String16 ifName = get_interface_name(service);
    131                 int32_t code = atoi(argv[optind++]);
    132                 if (service != NULL && ifName.size() > 0) {
    133                     Parcel data, reply;
    134 
    135                     // the interface name is first
    136                     data.writeInterfaceToken(ifName);
    137 
    138                     // then the rest of the call arguments
    139                     while (optind < argc) {
    140                         if (strcmp(argv[optind], "i32") == 0) {
    141                             optind++;
    142                             if (optind >= argc) {
    143                                 aerr << "service: no integer supplied for 'i32'" << endl;
    144                                 wantsUsage = true;
    145                                 result = 10;
    146                                 break;
    147                             }
    148                             data.writeInt32(atoi(argv[optind++]));
    149                         } else if (strcmp(argv[optind], "i64") == 0) {
    150                             optind++;
    151                             if (optind >= argc) {
    152                                 aerr << "service: no integer supplied for 'i64'" << endl;
    153                                 wantsUsage = true;
    154                                 result = 10;
    155                                 break;
    156                             }
    157                             data.writeInt64(atoll(argv[optind++]));
    158                         } else if (strcmp(argv[optind], "s16") == 0) {
    159                             optind++;
    160                             if (optind >= argc) {
    161                                 aerr << "service: no string supplied for 's16'" << endl;
    162                                 wantsUsage = true;
    163                                 result = 10;
    164                                 break;
    165                             }
    166                             data.writeString16(String16(argv[optind++]));
    167                         } else if (strcmp(argv[optind], "f") == 0) {
    168                             optind++;
    169                             if (optind >= argc) {
    170                                 aerr << "service: no number supplied for 'f'" << endl;
    171                                 wantsUsage = true;
    172                                 result = 10;
    173                                 break;
    174                             }
    175                             data.writeFloat(atof(argv[optind++]));
    176                         } else if (strcmp(argv[optind], "d") == 0) {
    177                             optind++;
    178                             if (optind >= argc) {
    179                                 aerr << "service: no number supplied for 'd'" << endl;
    180                                 wantsUsage = true;
    181                                 result = 10;
    182                                 break;
    183                             }
    184                             data.writeDouble(atof(argv[optind++]));
    185                         } else if (strcmp(argv[optind], "null") == 0) {
    186                             optind++;
    187                             data.writeStrongBinder(NULL);
    188                         } else if (strcmp(argv[optind], "intent") == 0) {
    189 
    190                         	char* action = NULL;
    191                         	char* dataArg = NULL;
    192                         	char* type = NULL;
    193                         	int launchFlags = 0;
    194                         	char* component = NULL;
    195                         	int categoryCount = 0;
    196                         	char* categories[16];
    197 
    198                         	char* context1 = NULL;
    199 
    200                             optind++;
    201 
    202                         	while (optind < argc)
    203                         	{
    204                         		char* key = strtok_r(argv[optind], "=", &context1);
    205                         		char* value = strtok_r(NULL, "=", &context1);
    206 
    207                                 // we have reached the end of the XXX=XXX args.
    208                                 if (key == NULL) break;
    209 
    210                         		if (strcmp(key, "action") == 0)
    211                         		{
    212                         			action = value;
    213                         		}
    214                         		else if (strcmp(key, "data") == 0)
    215                         		{
    216                         			dataArg = value;
    217                         		}
    218                         		else if (strcmp(key, "type") == 0)
    219                         		{
    220                         			type = value;
    221                         		}
    222                         		else if (strcmp(key, "launchFlags") == 0)
    223                         		{
    224                         			launchFlags = atoi(value);
    225                         		}
    226                         		else if (strcmp(key, "component") == 0)
    227                         		{
    228                         			component = value;
    229                         		}
    230                         		else if (strcmp(key, "categories") == 0)
    231                         		{
    232                         			char* context2 = NULL;
    233                         			int categoryCount = 0;
    234                         			categories[categoryCount] = strtok_r(value, ",", &context2);
    235 
    236                         			while (categories[categoryCount] != NULL)
    237                         			{
    238                         				categoryCount++;
    239                         				categories[categoryCount] = strtok_r(NULL, ",", &context2);
    240                         			}
    241                         		}
    242 
    243                                 optind++;
    244                         	}
    245 
    246                             writeString16(data, action);
    247                             writeString16(data, dataArg);
    248                             writeString16(data, type);
    249                        		data.writeInt32(launchFlags);
    250                             writeString16(data, component);
    251 
    252                             if (categoryCount > 0)
    253                             {
    254                                 data.writeInt32(categoryCount);
    255                                 for (int i = 0 ; i < categoryCount ; i++)
    256                                 {
    257                                     writeString16(data, categories[i]);
    258                                 }
    259                             }
    260                             else
    261                             {
    262                                 data.writeInt32(0);
    263                             }
    264 
    265                             // for now just set the extra field to be null.
    266                        		data.writeInt32(-1);
    267                         } else {
    268                             aerr << "service: unknown option " << argv[optind] << endl;
    269                             wantsUsage = true;
    270                             result = 10;
    271                             break;
    272                         }
    273                     }
    274 
    275                     service->transact(code, data, &reply);
    276                     aout << "Result: " << reply << endl;
    277                 } else {
    278                     aerr << "service: Service " << argv[serviceArg]
    279                         << " does not exist" << endl;
    280                     result = 10;
    281                 }
    282             } else {
    283                 if (optind < argc) {
    284                     aerr << "service: No service specified for call" << endl;
    285                 } else {
    286                     aerr << "service: No code specified for call" << endl;
    287                 }
    288                 wantsUsage = true;
    289                 result = 10;
    290             }
    291         } else {
    292             aerr << "service: Unknown command " << argv[optind] << endl;
    293             wantsUsage = true;
    294             result = 10;
    295         }
    296     }
    297 
    298     if (wantsUsage) {
    299         aout << "Usage: service [-h|-?]\n"
    300                 "       service list\n"
    301                 "       service check SERVICE\n"
    302                 "       service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...\n"
    303                 "Options:\n"
    304                 "   i32: Write the 32-bit integer N into the send parcel.\n"
    305                 "   i64: Write the 64-bit integer N into the send parcel.\n"
    306                 "   f:   Write the 32-bit single-precision number N into the send parcel.\n"
    307                 "   d:   Write the 64-bit double-precision number N into the send parcel.\n"
    308                 "   s16: Write the UTF-16 string STR into the send parcel.\n";
    309 //                "   intent: Write and Intent int the send parcel. ARGS can be\n"
    310 //                "       action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
    311         return result;
    312     }
    313 
    314     return result;
    315 }
    316 
    317