1/*
2 * Copyright (C) 2016 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 <benchmark/benchmark.h>
18
19#include <binder/IServiceManager.h>
20#include <binder/ProcessState.h>
21#include <utils/String16.h>
22#include <utils/StrongPointer.h>
23
24#include <sys/types.h>
25#include <sys/wait.h>
26#include <unistd.h>
27
28#include <android/tests/binder/IBenchmark.h>
29#include <android/tests/binder/BnBenchmark.h>
30
31// libutils:
32using android::OK;
33using android::sp;
34using android::status_t;
35using android::String16;
36
37// libbinder:
38using android::getService;
39using android::BnInterface;
40using android::defaultServiceManager;
41using android::ProcessState;
42using android::binder::Status;
43
44// Standard library
45using std::vector;
46
47// Generated AIDL files
48using android::tests::binder::BnBenchmark;
49using android::tests::binder::IBenchmark;
50
51const char kServiceName[] = "android.tests.binder.IBenchmark";
52
53class BenchmarkServiceAidl : public BnBenchmark {
54 public:
55    BenchmarkServiceAidl() {}
56    virtual ~BenchmarkServiceAidl() = default;
57
58    Status sendVec(const vector<uint8_t>& data, vector<uint8_t>* _aidl_return) {
59        *_aidl_return = data;
60        return Status::ok();
61    }
62};
63
64bool startServer() {
65    BenchmarkServiceAidl *service = new BenchmarkServiceAidl();
66    defaultServiceManager()->addService(String16(kServiceName),
67                                        service);
68    ProcessState::self()->startThreadPool();
69    return 0;
70}
71
72static void BM_sendVec_binder(benchmark::State& state) {
73    sp<IBenchmark> service;
74    // Prepare data to IPC
75    vector<uint8_t> data_vec;
76    vector<uint8_t> data_return;
77    data_vec.resize(state.range(0));
78    for (int i = 0; i < state.range(0); i++) {
79       data_vec[i] = i % 256;
80    }
81    // getService automatically retries
82    status_t status = getService(String16(kServiceName), &service);
83    if (status != OK) {
84        state.SkipWithError("Failed to retrieve benchmark service.");
85    }
86    // Start running
87    while (state.KeepRunning()) {
88       service->sendVec(data_vec, &data_return);
89    }
90}
91
92BENCHMARK(BM_sendVec_binder)->RangeMultiplier(2)->Range(4, 65536);
93
94int main(int argc, char* argv []) {
95    ::benchmark::Initialize(&argc, argv);
96
97    pid_t pid = fork();
98    if (pid == 0) {
99        // Child, start benchmarks
100        ::benchmark::RunSpecifiedBenchmarks();
101    } else {
102        int stat;
103        startServer();
104        while (true) {
105            int stat, retval;
106            retval = wait(&stat);
107            if (retval == -1 && errno == ECHILD) {
108                break;
109            }
110        }
111    };
112}
113