1 /*
2 * Copyright (C) 2018 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 "VersionedIDevice.h"
18
19 #include "Utils.h"
20
21 #include <android-base/logging.h>
22
23 namespace android {
24 namespace nn {
25
26 // HIDL guarantees all V1_1 interfaces inherit from their corresponding V1_0 interfaces.
VersionedIDevice(sp<V1_0::IDevice> device)27 VersionedIDevice::VersionedIDevice(sp<V1_0::IDevice> device) :
28 mDeviceV1_0(device),
29 mDeviceV1_1(V1_1::IDevice::castFrom(mDeviceV1_0).withDefault(nullptr)) {}
30
getCapabilities()31 std::pair<ErrorStatus, Capabilities> VersionedIDevice::getCapabilities() {
32 std::pair<ErrorStatus, Capabilities> result;
33
34 if (mDeviceV1_1 != nullptr) {
35 Return<void> ret = mDeviceV1_1->getCapabilities_1_1(
36 [&result](ErrorStatus error, const Capabilities& capabilities) {
37 result = std::make_pair(error, capabilities);
38 });
39 if (!ret.isOk()) {
40 LOG(ERROR) << "getCapabilities_1_1 failure: " << ret.description();
41 return {ErrorStatus::GENERAL_FAILURE, {}};
42 }
43 } else if (mDeviceV1_0 != nullptr) {
44 Return<void> ret = mDeviceV1_0->getCapabilities(
45 [&result](ErrorStatus error, const V1_0::Capabilities& capabilities) {
46 result = std::make_pair(error, convertToV1_1(capabilities));
47 });
48 if (!ret.isOk()) {
49 LOG(ERROR) << "getCapabilities failure: " << ret.description();
50 return {ErrorStatus::GENERAL_FAILURE, {}};
51 }
52 } else {
53 LOG(ERROR) << "Device not available!";
54 return {ErrorStatus::DEVICE_UNAVAILABLE, {}};
55 }
56
57 return result;
58 }
59
getSupportedOperations(const Model & model)60 std::pair<ErrorStatus, hidl_vec<bool>> VersionedIDevice::getSupportedOperations(
61 const Model& model) {
62 std::pair<ErrorStatus, hidl_vec<bool>> result;
63
64 if (mDeviceV1_1 != nullptr) {
65 Return<void> ret = mDeviceV1_1->getSupportedOperations_1_1(
66 model, [&result](ErrorStatus error, const hidl_vec<bool>& supported) {
67 result = std::make_pair(error, supported);
68 });
69 if (!ret.isOk()) {
70 LOG(ERROR) << "getSupportedOperations_1_1 failure: " << ret.description();
71 return {ErrorStatus::GENERAL_FAILURE, {}};
72 }
73 } else if (mDeviceV1_0 != nullptr && compliantWithV1_0(model)) {
74 Return<void> ret = mDeviceV1_0->getSupportedOperations(
75 convertToV1_0(model), [&result](ErrorStatus error, const hidl_vec<bool>& supported) {
76 result = std::make_pair(error, supported);
77 });
78 if (!ret.isOk()) {
79 LOG(ERROR) << "getSupportedOperations failure: " << ret.description();
80 return {ErrorStatus::GENERAL_FAILURE, {}};
81 }
82 } else {
83 // TODO: partition the model such that v1.1 ops are not passed to v1.0
84 // device
85 LOG(ERROR) << "Could not handle getSupportedOperations!";
86 return {ErrorStatus::GENERAL_FAILURE, {}};
87 }
88
89 return result;
90 }
91
prepareModel(const Model & model,ExecutionPreference preference,const sp<IPreparedModelCallback> & callback)92 ErrorStatus VersionedIDevice::prepareModel(const Model& model, ExecutionPreference preference,
93 const sp<IPreparedModelCallback>& callback) {
94 if (mDeviceV1_1 != nullptr) {
95 Return<ErrorStatus> ret = mDeviceV1_1->prepareModel_1_1(model, preference, callback);
96 if (!ret.isOk()) {
97 LOG(ERROR) << "prepareModel_1_1 failure: " << ret.description();
98 return ErrorStatus::GENERAL_FAILURE;
99 }
100 return static_cast<ErrorStatus>(ret);
101 } else if (mDeviceV1_0 != nullptr && compliantWithV1_0(model)) {
102 Return<ErrorStatus> ret = mDeviceV1_0->prepareModel(convertToV1_0(model), callback);
103 if (!ret.isOk()) {
104 LOG(ERROR) << "prepareModel failure: " << ret.description();
105 return ErrorStatus::GENERAL_FAILURE;
106 }
107 return static_cast<ErrorStatus>(ret);
108 } else {
109 // TODO: partition the model such that v1.1 ops are not passed to v1.0
110 // device
111 LOG(ERROR) << "Could not handle prepareModel!";
112 return ErrorStatus::GENERAL_FAILURE;
113 }
114 }
115
getStatus()116 DeviceStatus VersionedIDevice::getStatus() {
117 if (mDeviceV1_0 == nullptr) {
118 LOG(ERROR) << "Device not available!";
119 return DeviceStatus::UNKNOWN;
120 }
121
122 Return<DeviceStatus> ret = mDeviceV1_0->getStatus();
123
124 if (!ret.isOk()) {
125 LOG(ERROR) << "getStatus failure: " << ret.description();
126 return DeviceStatus::UNKNOWN;
127 }
128 return static_cast<DeviceStatus>(ret);
129 }
130
operator ==(nullptr_t)131 bool VersionedIDevice::operator==(nullptr_t) {
132 return mDeviceV1_0 == nullptr;
133 }
134
operator !=(nullptr_t)135 bool VersionedIDevice::operator!=(nullptr_t) {
136 return mDeviceV1_0 != nullptr;
137 }
138
139 } // namespace nn
140 } // namespace android
141