123eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn/*
223eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn * Copyright (C) 2015 The Android Open Source Project
323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn *
423eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
523eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn * you may not use this file except in compliance with the License.
623eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn * You may obtain a copy of the License at
723eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn *
823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn *
1023eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
1123eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
1223eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn * See the License for the specific language governing permissions and
1423eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn * limitations under the License.
1523eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn */
1623eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
1723eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#define LOG_TAG "cmd"
1823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
1923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <utils/Log.h>
2023eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <binder/Parcel.h>
2123eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <binder/ProcessState.h>
2223eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <binder/IResultReceiver.h>
2323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <binder/IServiceManager.h>
241941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn#include <binder/IShellCallback.h>
2523eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <binder/TextOutput.h>
263d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn#include <utils/Condition.h>
273d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn#include <utils/Mutex.h>
2823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <utils/Vector.h>
2923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
3023eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <getopt.h>
3123eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <stdlib.h>
3223eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <stdio.h>
3323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <string.h>
3423eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <unistd.h>
351941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn#include <fcntl.h>
3623eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn#include <sys/time.h>
371941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn#include <errno.h>
384e7d18a72f72967a881bcdf78167011a836538efJiyong Park#include <memory>
391941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn
401941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn#include "selinux/selinux.h"
411941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn#include "selinux/android.h"
421941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn
433d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn#define DEBUG 0
443d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn
4523eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackbornusing namespace android;
4623eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
4723eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackbornstatic int sort_func(const String16* lhs, const String16* rhs)
4823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn{
4923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    return lhs->compare(*rhs);
5023eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn}
5123eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
521941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackbornstruct SecurityContext_Delete {
531941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn    void operator()(security_context_t p) const {
541941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        freecon(p);
551941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn    }
561941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn};
574e7d18a72f72967a881bcdf78167011a836538efJiyong Parktypedef std::unique_ptr<char[], SecurityContext_Delete> Unique_SecurityContext;
581941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn
591941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackbornclass MyShellCallback : public BnShellCallback
601941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn{
611941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackbornpublic:
62e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn    bool mActive = true;
63e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn
644217f8ecfe8f884288104262000275c1633b983eDianne Hackborn    virtual int openFile(const String16& path, const String16& seLinuxContext,
654217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            const String16& mode) {
661941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        String8 path8(path);
671941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        char cwd[256];
681941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        getcwd(cwd, 256);
691941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        String8 fullPath(cwd);
701941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        fullPath.appendPath(path8);
71e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn        if (!mActive) {
72e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn            aerr << "Open attempt after active for: " << fullPath << endl;
73e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn            return -EPERM;
74e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn        }
75228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#if DEBUG
76228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn        ALOGD("openFile: %s, full=%s", path8.string(), fullPath.string());
77228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#endif
784217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        int flags = 0;
794217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        bool checkRead = false;
804217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        bool checkWrite = false;
814217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        if (mode == String16("w")) {
824217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            flags = O_WRONLY|O_CREAT|O_TRUNC;
834217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            checkWrite = true;
844217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        } else if (mode == String16("w+")) {
854217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            flags = O_RDWR|O_CREAT|O_TRUNC;
864217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            checkRead = checkWrite = true;
874217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        } else if (mode == String16("r")) {
884217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            flags = O_RDONLY;
894217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            checkRead = true;
904217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        } else if (mode == String16("r+")) {
914217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            flags = O_RDWR;
924217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            checkRead = checkWrite = true;
934217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        } else {
944217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            aerr << "Invalid mode requested: " << mode.string() << endl;
954217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            return -EINVAL;
964217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        }
974217f8ecfe8f884288104262000275c1633b983eDianne Hackborn        int fd = open(fullPath.string(), flags, S_IRWXU|S_IRWXG);
98228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#if DEBUG
99228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn        ALOGD("openFile: fd=%d", fd);
100228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#endif
1011941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        if (fd < 0) {
1021941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn            return fd;
1031941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        }
1041941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        if (is_selinux_enabled() && seLinuxContext.size() > 0) {
1051941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn            String8 seLinuxContext8(seLinuxContext);
1061941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn            security_context_t tmp = NULL;
107f463e180e5a69b4a43acd41c41c8518fa8c22b2dChih-Hung Hsieh            getfilecon(fullPath.string(), &tmp);
1081941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn            Unique_SecurityContext context(tmp);
1094217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            if (checkWrite) {
1104217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
1114217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                        "file", "write", NULL);
1124217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                if (accessGranted != 0) {
113228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#if DEBUG
114228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn                    ALOGD("openFile: failed selinux write check!");
115228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#endif
1164217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                    close(fd);
1174217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                    aerr << "System server has no access to write file context " << context.get()
1184217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                            << " (from path " << fullPath.string() << ", context "
1194217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                            << seLinuxContext8.string() << ")" << endl;
1204217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                    return -EPERM;
1214217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                }
1224217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            }
1234217f8ecfe8f884288104262000275c1633b983eDianne Hackborn            if (checkRead) {
1244217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
1254217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                        "file", "read", NULL);
1264217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                if (accessGranted != 0) {
127228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#if DEBUG
128228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn                    ALOGD("openFile: failed selinux read check!");
129228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#endif
1304217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                    close(fd);
1314217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                    aerr << "System server has no access to read file context " << context.get()
1324217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                            << " (from path " << fullPath.string() << ", context "
1334217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                            << seLinuxContext8.string() << ")" << endl;
1344217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                    return -EPERM;
1354217f8ecfe8f884288104262000275c1633b983eDianne Hackborn                }
1361941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn            }
1371941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        }
1381941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn        return fd;
1391941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn    }
1401941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn};
1411941a404d642b3dfaac365ba494f1e9912876f00Dianne Hackborn
14223eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackbornclass MyResultReceiver : public BnResultReceiver
14323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn{
14423eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackbornpublic:
1453d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    Mutex mMutex;
1463d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    Condition mCondition;
1473d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    bool mHaveResult = false;
1483d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    int32_t mResult = 0;
1493d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn
1503d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    virtual void send(int32_t resultCode) {
1513d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        AutoMutex _l(mMutex);
1523d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        mResult = resultCode;
1533d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        mHaveResult = true;
1543d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        mCondition.signal();
1553d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    }
1563d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn
1573d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    int32_t waitForResult() {
1583d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        AutoMutex _l(mMutex);
1593d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        while (!mHaveResult) {
1603d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn            mCondition.wait(mMutex);
1613d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        }
1623d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        return mResult;
16323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    }
16423eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn};
16523eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
16623eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackbornint main(int argc, char* const argv[])
16723eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn{
16823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    signal(SIGPIPE, SIG_IGN);
16923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    sp<ProcessState> proc = ProcessState::self();
170c21bc9afe403f52c189d2d6b79dedaf9dce6217bMartijn Coenen    // setThreadPoolMaxThreadCount(0) actually tells the kernel it's
171c21bc9afe403f52c189d2d6b79dedaf9dce6217bMartijn Coenen    // not allowed to spawn any additional threads, but we still spawn
172c21bc9afe403f52c189d2d6b79dedaf9dce6217bMartijn Coenen    // a binder thread from userspace when we call startThreadPool().
173c21bc9afe403f52c189d2d6b79dedaf9dce6217bMartijn Coenen    // This is safe because we only have 2 callbacks, neither of which
174c21bc9afe403f52c189d2d6b79dedaf9dce6217bMartijn Coenen    // block.
175c21bc9afe403f52c189d2d6b79dedaf9dce6217bMartijn Coenen    // See b/36066697 for rationale
176c21bc9afe403f52c189d2d6b79dedaf9dce6217bMartijn Coenen    proc->setThreadPoolMaxThreadCount(0);
17723eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    proc->startThreadPool();
17823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
179228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#if DEBUG
180228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn    ALOGD("cmd: starting");
181228f2f66318e97da7c9d13fdc9f28ebddaa1fb46Dianne Hackborn#endif
18223eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    sp<IServiceManager> sm = defaultServiceManager();
18323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    fflush(stdout);
18423eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    if (sm == NULL) {
1853d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        ALOGW("Unable to get default service manager!");
18623eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        aerr << "cmd: Unable to get default service manager!" << endl;
18723eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        return 20;
18823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    }
18923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
19023eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    if (argc == 1) {
1913d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        aerr << "cmd: No service specified; use -l to list all services" << endl;
19223eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        return 20;
19323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    }
19423eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
19523eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
19623eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        Vector<String16> services = sm->listServices();
19723eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        services.sort(sort_func);
19823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        aout << "Currently running services:" << endl;
19923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
20023eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        for (size_t i=0; i<services.size(); i++) {
20123eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn            sp<IBinder> service = sm->checkService(services[i]);
20223eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn            if (service != NULL) {
20323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn                aout << "  " << services[i] << endl;
20423eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn            }
20523eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        }
20623eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        return 0;
20723eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    }
20823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
20923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    Vector<String16> args;
21023eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    for (int i=2; i<argc; i++) {
21123eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        args.add(String16(argv[i]));
21223eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    }
21323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    String16 cmd = String16(argv[1]);
21423eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    sp<IBinder> service = sm->checkService(cmd);
21523eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    if (service == NULL) {
2163d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        ALOGW("Can't find service %s", argv[1]);
2173d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        aerr << "cmd: Can't find service: " << argv[1] << endl;
21823eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn        return 20;
21923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    }
22023eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn
221e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn    sp<MyShellCallback> cb = new MyShellCallback();
2223d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    sp<MyResultReceiver> result = new MyResultReceiver();
2233d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn
2243d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn#if DEBUG
2253d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    ALOGD("cmd: Invoking %s in=%d, out=%d, err=%d", argv[1], STDIN_FILENO, STDOUT_FILENO,
2263d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn            STDERR_FILENO);
2273d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn#endif
228e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn
22923eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn    // TODO: block until a result is returned to MyResultReceiver.
2303d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    status_t err = IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
2313d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn            cb, result);
2323d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    if (err < 0) {
2333d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        const char* errstr;
2343d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        switch (err) {
2353d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn            case BAD_TYPE: errstr = "Bad type"; break;
2363d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn            case FAILED_TRANSACTION: errstr = "Failed transaction"; break;
2373d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn            case FDS_NOT_ALLOWED: errstr = "File descriptors not allowed"; break;
2383d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn            case UNEXPECTED_NULL: errstr = "Unexpected null"; break;
2393d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn            default: errstr = strerror(-err); break;
2403d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        }
2413d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        ALOGW("Failure calling service %s: %s (%d)", argv[1], errstr, -err);
2423d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        aout << "cmd: Failure calling service " << argv[1] << ": " << errstr << " ("
2433d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn                << (-err) << ")" << endl;
2443d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn        return err;
2453d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    }
246e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn
247e5ed19999d724b6f5131803ff56b3536349b58deDianne Hackborn    cb->mActive = false;
2483d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    status_t res = result->waitForResult();
2493d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn#if DEBUG
2503d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    ALOGD("result=%d", (int)res);
2513d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn#endif
2523d9eb950b14ee6527a5a85d669bd03ce2bdcff32Dianne Hackborn    return res;
25323eb1e20cf59e1238b65cc108f31dfbfd85b2337Dianne Hackborn}
254