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 "Weaver.h"
18
19#include <android-base/logging.h>
20
21#include <Weaver.h>
22#include <Weaver.client.h>
23
24namespace android {
25namespace hardware {
26namespace weaver {
27
28// libhidl
29using ::android::hardware::Void;
30
31// HAL
32using ::android::hardware::weaver::V1_0::WeaverConfig;
33using ::android::hardware::weaver::V1_0::WeaverReadResponse;
34using ::android::hardware::weaver::V1_0::WeaverReadStatus;
35
36// Weaver app
37using ::nugget::app::weaver::GetConfigRequest;
38using ::nugget::app::weaver::GetConfigResponse;
39using ::nugget::app::weaver::ReadRequest;
40using ::nugget::app::weaver::ReadResponse;
41using ::nugget::app::weaver::WriteRequest;
42using ::nugget::app::weaver::WriteResponse;
43
44// Methods from ::android::hardware::weaver::V1_0::IWeaver follow.
45Return<void> Weaver::getConfig(getConfig_cb _hidl_cb) {
46    LOG(VERBOSE) << "Running Weaver::getNumSlots";
47
48    GetConfigRequest request;
49    GetConfigResponse response;
50    const uint32_t appStatus = _weaver.GetConfig(request, &response);
51
52    if (appStatus != APP_SUCCESS) {
53        LOG(ERROR) << "App GetConfig request failed with status " << appStatus;
54        _hidl_cb(WeaverStatus::FAILED, WeaverConfig{});
55        return Void();
56    }
57
58    _hidl_cb(WeaverStatus::OK,
59             WeaverConfig{response.number_of_slots(), response.key_size(), response.value_size()});
60    return Void();
61}
62
63Return<WeaverStatus> Weaver::write(uint32_t slotId, const hidl_vec<uint8_t>& key,
64                           const hidl_vec<uint8_t>& value) {
65    LOG(INFO) << "Running Weaver::write on slot " << slotId;
66
67    WriteRequest request;
68    request.set_slot(slotId);
69    request.set_key(key.data(), key.size());
70    request.set_value(value.data(), value.size());
71    WriteResponse response;
72    const uint32_t appStatus = _weaver.Write(request, &response);
73
74    if (appStatus != APP_SUCCESS) {
75        LOG(ERROR) << "App Write request failed with status " << appStatus;
76        return WeaverStatus::FAILED;
77    }
78
79    return WeaverStatus::OK;
80}
81
82Return<void> Weaver::read(uint32_t slotId, const hidl_vec<uint8_t>& key, read_cb _hidl_cb) {
83    LOG(VERBOSE) << "Running Weaver::read on slot " << slotId;
84
85    ReadRequest request;
86    request.set_slot(slotId);
87    request.set_key(key.data(), key.size());
88    ReadResponse response;
89    const uint32_t appStatus = _weaver.Read(request, &response);
90
91    if (appStatus != APP_SUCCESS) {
92        LOG(ERROR) << "App Read request failed with status " << appStatus;
93        _hidl_cb(WeaverReadStatus::FAILED, WeaverReadResponse{});
94        return Void();
95    }
96
97    WeaverReadStatus status;
98    hidl_vec<uint8_t> value;
99    uint32_t timeout = 0;
100    switch (response.error()) {
101    case ReadResponse::NONE:
102        status = WeaverReadStatus::OK;
103        value.setToExternal(reinterpret_cast<uint8_t*>(const_cast<char*>(response.value().data())),
104                            response.value().size(), false);
105        break;
106    case ReadResponse::WRONG_KEY:
107        LOG(WARNING) << "Wrong key used when reading slot " << slotId;
108        status = WeaverReadStatus::INCORRECT_KEY;
109        timeout = response.throttle_msec();
110        break;
111    case ReadResponse::THROTTLE:
112        LOG(WARNING) << "Attempted to read slot " << slotId << " when throttling is active";
113        status = WeaverReadStatus::THROTTLE;
114        timeout = response.throttle_msec();
115        break;
116    default:
117        LOG(ERROR) << "Unexpected error code from app (" << response.error() << ")";
118        status = WeaverReadStatus::FAILED;
119        break;
120    }
121
122    _hidl_cb(status, WeaverReadResponse{timeout, value});
123    return Void();
124}
125
126} // namespace weaver
127} // namespace hardware
128} // namespace android
129