1/*
2 * Copyright (C) 2017 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 <nos/CitadeldProxyClient.h>
18
19#include <android-base/logging.h>
20#include <binder/IServiceManager.h>
21#include <binder/ProcessState.h>
22
23#include <application.h>
24
25using ::android::defaultServiceManager;
26using ::android::sp;
27using ::android::IServiceManager;
28using ::android::ProcessState;
29
30using ::android::binder::Status;
31
32using ::android::hardware::citadel::ICitadeld;
33
34namespace nos {
35
36CitadeldProxyClient::~CitadeldProxyClient() {
37    Close();
38}
39
40void CitadeldProxyClient::Open() {
41    // Ensure this process is using the vndbinder
42    ProcessState::initWithDriver("/dev/vndbinder");
43    _citadeld = ICitadeld::asInterface(defaultServiceManager()->getService(ICitadeld::descriptor));
44}
45
46void CitadeldProxyClient::Close() {
47    _citadeld.clear();
48}
49
50bool CitadeldProxyClient::IsOpen() const {
51    return _citadeld != nullptr;
52}
53
54uint32_t CitadeldProxyClient::CallApp(uint32_t appId, uint16_t arg,
55                                      const std::vector<uint8_t>& request,
56                                      std::vector<uint8_t>* _response) {
57    // Binder doesn't pass a nullptr or the capacity so resolve the response
58    // buffer size before making the call. The response vector may be the same
59    // as the request vector so the response cannot be directly resized.
60    std::vector<uint8_t> response(_response == nullptr ? 0 : _response->capacity());
61
62    uint32_t appStatus;
63    Status status = _citadeld->callApp(appId, arg, request, &response,
64                                       reinterpret_cast<int32_t*>(&appStatus));
65    if (status.isOk()) {
66        if (_response != nullptr) {
67            *_response = std::move(response);
68        }
69        return appStatus;
70    }
71    LOG(ERROR) << "Failed to call app via citadeld: " << status.toString8();
72    return APP_ERROR_IO;
73}
74
75ICitadeld& CitadeldProxyClient::Citadeld() {
76    return *_citadeld.get();
77}
78
79} // namespace nos
80