using android::base::unique_fd;
using android::base::WriteFully;
-static int sort_func(const String16* lhs, const String16* rhs)
-{
+static int sort_func(const String16* lhs, const String16* rhs) {
return lhs->compare(*rhs);
}
"usage: dumpsys\n"
" To dump all services.\n"
"or:\n"
- " dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
+ " dumpsys [-t TIMEOUT] [--help | --hw | -l | --skip SERVICES | SERVICE [ARGS]]\n"
" --help: shows this help\n"
" -l: only list services, do not dump them\n"
" -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
+ " --hw: list all hw services running on the device\n"
" --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
" SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
}
return false;
}
+static void ListHardwareServices(android::hidl::manager::V1_0::IServiceManager* hm) {
+ using android::hardware::hidl_vec;
+ using android::hardware::hidl_string;
+ using android::hardware::Return;
+ using android::sp;
+
+ if (hm == nullptr) {
+ ALOGE("Unable to get hardware service manager!");
+ aerr << "Failed to get hardware service manager!";
+ return;
+ }
+
+ Return<void> ret = hm->list([](const hidl_vec<hidl_string> ®istered){
+ aout << "Currently running hardware services:" << endl;
+ for (const auto &service : registered) {
+ aout << " " << service << endl;
+ }
+ });
+
+ if (!ret.isOk()) {
+ aerr << "Failed to list hardware services: " << ret.description();
+ }
+}
+
int Dumpsys::main(int argc, char* const argv[]) {
Vector<String16> services;
Vector<String16> args;
Vector<String16> skippedServices;
bool showListOnly = false;
+ bool listHwOnly = false;
bool skipServices = false;
int timeoutArg = 10;
static struct option longOptions[] = {
{"skip", no_argument, 0, 0 },
{"help", no_argument, 0, 0 },
+ {"hw", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
};
} else if (!strcmp(longOptions[optionIndex].name, "help")) {
usage();
return 0;
+ } else if (!strcmp(longOptions[optionIndex].name, "hw")) {
+ listHwOnly = true;
}
break;
}
if ((skipServices && skippedServices.empty()) ||
- (showListOnly && (!services.empty() || !skippedServices.empty()))) {
+ (showListOnly && (!services.empty() || !skippedServices.empty())) ||
+ (listHwOnly && (skipServices || services.size() > 0 || showListOnly))) {
usage();
return -1;
}
+ if (listHwOnly) {
+ ListHardwareServices(hm_);
+ return 0;
+ }
+
if (services.empty() || showListOnly) {
// gets all services
services = sm_->listServices();
using ::testing::internal::GetCapturedStderr;
using ::testing::internal::GetCapturedStdout;
+using android::hardware::hidl_vec;
+using android::hardware::hidl_string;
+using android::hardware::Void;
+using HServiceManager = android::hidl::manager::V1_0::IServiceManager;
+using IServiceNotification = android::hidl::manager::V1_0::IServiceNotification;
+
class ServiceManagerMock : public IServiceManager {
public:
MOCK_CONST_METHOD1(getService, sp<IBinder>(const String16&));
MOCK_METHOD0(onAsBinder, IBinder*());
};
+class HardwareServiceManagerMock : public HServiceManager {
+ public:
+ template<typename T>
+ using R = android::hardware::Return<T>; // conflicts with ::testing::Return
+
+ MOCK_METHOD2(get, R<sp<IBase>>(const hidl_string&, const hidl_string&));
+ MOCK_METHOD3(add,
+ R<bool>(const hidl_vec<hidl_string>&,
+ const hidl_string&,
+ const sp<IBase>&));
+ MOCK_METHOD1(list, R<void>(list_cb));
+ MOCK_METHOD2(listByInterface,
+ R<void>(const hidl_string&, listByInterface_cb));
+ MOCK_METHOD3(registerForNotifications,
+ R<bool>(const hidl_string&,
+ const hidl_string&,
+ const sp<IServiceNotification>&));
+
+};
+
class BinderMock : public BBinder {
public:
BinderMock() {
return MakeAction(new WriteOnFdAction(output));
}
+// gmock black magic to provide a WithArg<0>(List(services)) matcher
+typedef void HardwareListFunction(HServiceManager::list_cb);
+
+class HardwareListAction : public ActionInterface<HardwareListFunction> {
+ public:
+ explicit HardwareListAction(const hidl_vec<hidl_string> &services) : services_(services) {
+ }
+ virtual Result Perform(const ArgumentTuple& args) {
+ auto cb = ::std::tr1::get<0>(args);
+ cb(services_);
+ }
+
+ private:
+ hidl_vec<hidl_string> services_;
+};
+
+Action<HardwareListFunction> HardwareList(const hidl_vec<hidl_string> &services) {
+ return MakeAction(new HardwareListAction(services));
+}
+
// Matcher for args using Android's Vector<String16> format
// TODO: move it to some common testing library
MATCHER_P(AndroidElementsAre, expected, "") {
class DumpsysTest : public Test {
public:
- DumpsysTest() : sm_(), dump_(&sm_), stdout_(), stderr_() {
+ DumpsysTest() : sm_(), hm_(), dump_(&sm_, &hm_), stdout_(), stderr_() {
}
void ExpectListServices(std::vector<std::string> services) {
for (auto& service : services) {
services16.add(String16(service.c_str()));
}
+
EXPECT_CALL(sm_, listServices()).WillRepeatedly(Return(services16));
}
+ void ExpectListHardwareServices(std::vector<std::string> services) {
+ hidl_vec<hidl_string> hidl_services;
+ hidl_services.resize(services.size());
+ for (size_t i = 0; i < services.size(); i++) {
+ hidl_services[i] = services[i];
+ }
+
+ EXPECT_CALL(hm_, list(_)).WillRepeatedly(DoAll(
+ WithArg<0>(HardwareList(hidl_services)),
+ Return(Void())));
+ }
+
sp<BinderMock> ExpectCheckService(const char* name, bool running = true) {
sp<BinderMock> binder_mock;
if (running) {
EXPECT_THAT(status, Eq(0));
}
- void AssertRunningServices(const std::vector<std::string>& services) {
- std::string expected("Currently running services:\n");
+ void AssertRunningServices(const std::vector<std::string>& services,
+ const std::string &message = "Currently running services:") {
+ std::string expected(message);
+ expected.append("\n");
for (const std::string& service : services) {
expected.append(" ").append(service).append("\n");
}
}
ServiceManagerMock sm_;
+ HardwareServiceManagerMock hm_;
Dumpsys dump_;
private:
std::string stdout_, stderr_;
};
+TEST_F(DumpsysTest, ListHwServices) {
+ ExpectListHardwareServices({"Locksmith", "Valet"});
+
+ CallMain({"--hw"});
+
+ AssertRunningServices({"Locksmith", "Valet"}, "Currently running hardware services:");
+}
+
// Tests 'dumpsys -l' when all services are running
TEST_F(DumpsysTest, ListAllServices) {
ExpectListServices({"Locksmith", "Valet"});