blob: 5692635ae5ffb9b2ef33d71cc987521fd81e5f89 [file] [log] [blame]
#include "hasher.h"
#include <iostream>
#include <map>
#include <unistd.h>
#include <hwbinder/IInterface.h>
#include <hwbinder/IPCThreadState.h>
#include <hwbinder/IServiceManager.h>
#include <hwbinder/ProcessState.h>
#include <hwbinder/Status.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>
#include <BnTypes.h>
#include <ISmallTest.h>
// libutils:
using android::Looper;
using android::LooperCallback;
using android::OK;
using android::sp;
using android::String16;
// libhwbinder:
using android::hardware::BnInterface;
using android::hardware::defaultServiceManager;
using android::hardware::IInterface;
using android::hardware::IPCThreadState;
using android::hardware::Parcel;
using android::hardware::ProcessState;
using android::hardware::Status;
using android::hardware::hidl_version;
using android::hardware::make_hidl_version;
using android::hardware::from_ref;
// Standard library
using std::cerr;
using std::cout;
using std::endl;
using std::map;
using std::string;
using std::unique_ptr;
using std::vector;
// Generated HIDL files
using android::hardware::tests::BnTypes;
namespace {
class BinderCallback : public LooperCallback {
public:
BinderCallback() {}
~BinderCallback() override {}
int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
IPCThreadState::self()->handlePolledCommands();
return 1; // Continue receiving callbacks.
}
};
class Types : public BnTypes {
public:
Types() {}
virtual ~Types() = default;
virtual Status echoInteger(int32_t echo_me, const ITypes::simple_t& my_struct, ITypes::echoInteger_cb callback) {
//std::cout << "struct at addr " << (void *)&my_struct << std::endl;
//std::cout << "int1 " << my_struct.int1 << " int 2 " << my_struct.int2 << std::endl;
addHash(echo_me);
addHash(my_struct.int1);
addHash(my_struct.int2);
callback(echo_me);
return Status::ok();
}
// Proves we can receive an interface through HwBinder from the client,
// call one of its functions successfully, and echo the interface back
// to the client.
virtual Status echoInterface(sp<android::hardware::tests::ISmallTest> cb_t,
ITypes::echoInterface_cb callback) {
// cb_t should be a viable HwBinder object implementing IC
bool all_is_happy = false;
cb_t->echoNumber(42, [&](const uint32_t should_be_42) {
if (should_be_42 == 42) {
all_is_happy = true;
} else {
// TODO(cphoenix): Printf's aren't the right way to deal with errors
printf("Bad value %d received in server-side callback test\n",
should_be_42);
}
});
if (!all_is_happy) {
printf("Error in server-side callbackTest (check if callback was called)\n");
}
callback(cb_t);
return Status::ok();
}
virtual Status shareBufferWithRef(int buffer, ITypes::shareBufferWithRef_cb callback) {
// Map back to struct lots_of_data
ITypes::lots_of_data* dataPtr;
if (from_ref(buffer, &dataPtr)) {
// Failed
callback(-1);
} else {
// cout << "Data element at position 1481 is " << unsigned(dataPtr->buffer[1481]) << endl;
addHash(dataPtr->buffer[1481]);
callback(int32_t(dataPtr->buffer[1481]));
}
return Status::ok();
}
virtual Status echoEnum(eu8 a, es8 b, eu16 c, es16 d, eu32 e, es32 f, eu64 g, es64 h, ec i, ITypes::echoEnum_cb cb) {
addHash((uint8_t)a);
addHash((int8_t)b);
addHash((uint16_t)c);
addHash((int16_t)d);
addHash((uint32_t)e);
addHash((int32_t)f);
addHash((uint64_t)g);
addHash((int64_t)h);
addHash((uint8_t)i);
cb(a, b, c, d, e, f, g, h, i);
return Status::ok();
}
virtual Status echoScalar(uint8_t a, int8_t b, uint16_t c, int16_t d, uint32_t e, int32_t f, uint64_t g, int64_t h, char i, ITypes::echoScalar_cb cb) {
addHash(a);
addHash(b);
addHash(c);
addHash(d);
addHash(e);
addHash(f);
addHash(g);
addHash(h);
addHash(i);
cb(a, b, c, d, e, f, g, h, i);
return Status::ok();
}
virtual Status echoStruct(const ITypes::s0 &s, ITypes::echoStruct_cb cb) {
cout << "Server: echoStruct called" << endl;
cout << "Server: in echoStruct, s is " << &s << endl;
int i = s.s1v2.count;
cout << "S: vec count(2?): " << i << endl;
printf("S: s1m1 len is %ld\n", s.s1m1.str1.length);
printf("S: s %p s.s1m1.str1.buf %p s.s1v2.buf %p\n",
&s, s.s1m1.str1.buffer, s.s1v2.buffer);
printf("S: * s.s1v2.buf[0].str1.buf %p [1] %p\n", s.s1v2.buffer[0].str1.buffer, s.s1v2.buffer[1].str1.buffer);
printf("S: s1m1 str is %s\n", s.s1m1.str1.buffer);
printf("S: s1v2[0] len is %ld\n", s.s1v2.buffer[0].str1.length);
printf("S: s1v2[0] str is %s\n", s.s1v2.buffer[0].str1.buffer);
printf("S: s1v2[1] len is %ld\n", s.s1v2.buffer[1].str1.length);
printf("S: s1v2[1] bytes is %c%c%c%c%c\n", s.s1v2.buffer[1].str1.buffer[0],
s.s1v2.buffer[1].str1.buffer[1],s.s1v2.buffer[1].str1.buffer[2],
s.s1v2.buffer[1].str1.buffer[3],s.s1v2.buffer[1].str1.buffer[4]);
cb(s);
cout << "Server: echoStruct survived cb(s)" << endl;
return Status::ok();
}
virtual Status getHash(ITypes::getHash_cb cb) {
cb(::getHash());
return Status::ok();
}
virtual Status quit() {
//cout << "Service: quitting" << endl;
fflush(stdout);
exit(0);
}
private:
};
int Run() {
android::sp<Types::Types> service = new Types::Types;
//cout << "Service started." << endl;
//fflush(stdout);
sp<Looper> looper(Looper::prepare(0 /* opts */));
int binder_fd = -1;
ProcessState::self()->setThreadPoolMaxThreadCount(0);
IPCThreadState::self()->disableBackgroundScheduling(true);
IPCThreadState::self()->setupPolling(&binder_fd);
ALOGI("Got binder FD %d", binder_fd);
if (binder_fd < 0) return -1;
sp<BinderCallback> cb(new BinderCallback);
if (looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb,
nullptr) != 1) {
ALOGE("Failed to add binder FD to Looper");
return -1;
}
hidl_version version = android::hardware::make_hidl_version(4,1);
defaultServiceManager()->addService(service->getInterfaceDescriptor(),
service, version);
ALOGI("Entering loop");
while (true) {
const int result = looper->pollAll(-1 /* timeoutMillis */);
ALOGI("Looper returned %d", result);
}
return 0;
}
} // namespace
int main(int /* argc */, char* /* argv */ []) {
return Run();
}