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], "s16") == 0) {
    150                             optind++;
    151                             if (optind >= argc) {
    152                                 aerr << "service: no string supplied for 's16'" << endl;
    153                                 wantsUsage = true;
    154                                 result = 10;
    155                                 break;
    156                             }
    157                             data.writeString16(String16(argv[optind++]));
    158                         } else if (strcmp(argv[optind], "null") == 0) {
    159                             optind++;
    160                             data.writeStrongBinder(NULL);
    161                         } else if (strcmp(argv[optind], "intent") == 0) {
    162 
    163                         	char* action = NULL;
    164                         	char* dataArg = NULL;
    165                         	char* type = NULL;
    166                         	int launchFlags = 0;
    167                         	char* component = NULL;
    168                         	int categoryCount = 0;
    169                         	char* categories[16];
    170 
    171                         	char* context1 = NULL;
    172 
    173                             optind++;
    174 
    175                         	while (optind < argc)
    176                         	{
    177                         		char* key = strtok_r(argv[optind], "=", &context1);
    178                         		char* value = strtok_r(NULL, "=", &context1);
    179 
    180                                 // we have reached the end of the XXX=XXX args.
    181                                 if (key == NULL) break;
    182 
    183                         		if (strcmp(key, "action") == 0)
    184                         		{
    185                         			action = value;
    186                         		}
    187                         		else if (strcmp(key, "data") == 0)
    188                         		{
    189                         			dataArg = value;
    190                         		}
    191                         		else if (strcmp(key, "type") == 0)
    192                         		{
    193                         			type = value;
    194                         		}
    195                         		else if (strcmp(key, "launchFlags") == 0)
    196                         		{
    197                         			launchFlags = atoi(value);
    198                         		}
    199                         		else if (strcmp(key, "component") == 0)
    200                         		{
    201                         			component = value;
    202                         		}
    203                         		else if (strcmp(key, "categories") == 0)
    204                         		{
    205                         			char* context2 = NULL;
    206                         			int categoryCount = 0;
    207                         			categories[categoryCount] = strtok_r(value, ",", &context2);
    208 
    209                         			while (categories[categoryCount] != NULL)
    210                         			{
    211                         				categoryCount++;
    212                         				categories[categoryCount] = strtok_r(NULL, ",", &context2);
    213                         			}
    214                         		}
    215 
    216                                 optind++;
    217                         	}
    218 
    219                             writeString16(data, action);
    220                             writeString16(data, dataArg);
    221                             writeString16(data, type);
    222                        		data.writeInt32(launchFlags);
    223                             writeString16(data, component);
    224 
    225                             if (categoryCount > 0)
    226                             {
    227                                 data.writeInt32(categoryCount);
    228                                 for (int i = 0 ; i < categoryCount ; i++)
    229                                 {
    230                                     writeString16(data, categories[i]);
    231                                 }
    232                             }
    233                             else
    234                             {
    235                                 data.writeInt32(0);
    236                             }
    237 
    238                             // for now just set the extra field to be null.
    239                        		data.writeInt32(-1);
    240                         } else {
    241                             aerr << "service: unknown option " << argv[optind] << endl;
    242                             wantsUsage = true;
    243                             result = 10;
    244                             break;
    245                         }
    246                     }
    247 
    248                     service->transact(code, data, &reply);
    249                     aout << "Result: " << reply << endl;
    250                 } else {
    251                     aerr << "service: Service " << argv[serviceArg]
    252                         << " does not exist" << endl;
    253                     result = 10;
    254                 }
    255             } else {
    256                 if (optind < argc) {
    257                     aerr << "service: No service specified for call" << endl;
    258                 } else {
    259                     aerr << "service: No code specified for call" << endl;
    260                 }
    261                 wantsUsage = true;
    262                 result = 10;
    263             }
    264         } else {
    265             aerr << "service: Unknown command " << argv[optind] << endl;
    266             wantsUsage = true;
    267             result = 10;
    268         }
    269     }
    270 
    271     if (wantsUsage) {
    272         aout << "Usage: service [-h|-?]\n"
    273                 "       service list\n"
    274                 "       service check SERVICE\n"
    275                 "       service call SERVICE CODE [i32 INT | s16 STR] ...\n"
    276                 "Options:\n"
    277                 "   i32: Write the integer INT into the send parcel.\n"
    278                 "   s16: Write the UTF-16 string STR into the send parcel.\n";
    279 //                "   intent: Write and Intent int the send parcel. ARGS can be\n"
    280 //                "       action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
    281         return result;
    282     }
    283 
    284     return result;
    285 }
    286 
    287