Merge "neuralnetworks: fix out ParcelFileDescriptor" am: 1f37668552

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1607935

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I908a225032724c68c7392bcf0b505ee120423c19
This commit is contained in:
Jooyung Han
2021-03-02 02:22:56 +00:00
committed by Automerger Merge Worker
7 changed files with 101 additions and 31 deletions

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
// two cases:
// 1). this is a frozen version file - do not edit this in any case.
// 2). this is a 'current' file. If you make a backwards compatible change to
// the interface (from the latest frozen version), the build system will
// prompt you to update this file with `m <name>-update-api`.
//
// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.neuralnetworks;
@VintfStability
parcelable FencedExecutionResult {
android.hardware.neuralnetworks.IFencedExecutionCallback callback;
@nullable ParcelFileDescriptor syncFence;
}

View File

@@ -34,7 +34,7 @@ package android.hardware.neuralnetworks;
@VintfStability @VintfStability
interface IPreparedModel { interface IPreparedModel {
android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadline, in long loopTimeoutDuration); android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadline, in long loopTimeoutDuration);
android.hardware.neuralnetworks.IFencedExecutionCallback executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadline, in long loopTimeoutDuration, in long duration, out @nullable ParcelFileDescriptor syncFence); android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadline, in long loopTimeoutDuration, in long duration);
const long DEFAULT_LOOP_TIMEOUT_DURATION_NS = 2000000000; const long DEFAULT_LOOP_TIMEOUT_DURATION_NS = 2000000000;
const long MAXIMUM_LOOP_TIMEOUT_DURATION_NS = 15000000000; const long MAXIMUM_LOOP_TIMEOUT_DURATION_NS = 15000000000;
} }

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.neuralnetworks;
import android.hardware.neuralnetworks.IFencedExecutionCallback;
/**
* A result from running an asynchronous execution of a prepared model.
*/
@VintfStability
parcelable FencedExecutionResult {
/**
* IFencedExecutionCallback can be used to query information like duration and error
* status when the execution is completed.
*/
IFencedExecutionCallback callback;
/**
* The sync fence that will be signaled when the task is completed. The
* sync fence will be set to error if a critical error, e.g. hardware
* failure or kernel panic, occurs when doing execution.
*/
@nullable ParcelFileDescriptor syncFence;
}

View File

@@ -19,7 +19,7 @@ package android.hardware.neuralnetworks;
import android.hardware.common.NativeHandle; import android.hardware.common.NativeHandle;
import android.hardware.neuralnetworks.ErrorStatus; import android.hardware.neuralnetworks.ErrorStatus;
import android.hardware.neuralnetworks.ExecutionResult; import android.hardware.neuralnetworks.ExecutionResult;
import android.hardware.neuralnetworks.IFencedExecutionCallback; import android.hardware.neuralnetworks.FencedExecutionResult;
import android.hardware.neuralnetworks.Request; import android.hardware.neuralnetworks.Request;
/** /**
@@ -152,11 +152,8 @@ interface IPreparedModel {
* complete after all sync fences in waitFor are signaled. If the execution * complete after all sync fences in waitFor are signaled. If the execution
* cannot be finished within the duration, the execution may be aborted. Passing * cannot be finished within the duration, the execution may be aborted. Passing
* -1 means the duration is omitted. Other negative values are invalid. * -1 means the duration is omitted. Other negative values are invalid.
* @param out syncFence The sync fence that will be signaled when the task is completed. The * @return The FencedExecutionResult parcelable, containing IFencedExecutionCallback and the
* sync fence will be set to error if a critical error, e.g. hardware * sync fence.
* failure or kernel panic, occurs when doing execution.
* @return The IFencedExecutionCallback can be used to query information like duration and error
* status when the execution is completed.
* @throws ServiceSpecificException with one of the following ErrorStatus values: * @throws ServiceSpecificException with one of the following ErrorStatus values:
* - DEVICE_UNAVAILABLE if driver is offline or busy * - DEVICE_UNAVAILABLE if driver is offline or busy
* - GENERAL_FAILURE if there is an unspecified error * - GENERAL_FAILURE if there is an unspecified error
@@ -166,7 +163,7 @@ interface IPreparedModel {
* deadline * deadline
* - RESOURCE_EXHAUSTED_* if the task was aborted by the driver * - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
*/ */
IFencedExecutionCallback executeFenced(in Request request, in ParcelFileDescriptor[] waitFor, FencedExecutionResult executeFenced(in Request request, in ParcelFileDescriptor[] waitFor,
in boolean measureTiming, in long deadline, in long loopTimeoutDuration, in boolean measureTiming, in long deadline, in long loopTimeoutDuration,
in long duration, out @nullable ParcelFileDescriptor syncFence); in long duration);
} }

View File

@@ -571,33 +571,32 @@ void EvaluatePreparedModel(const std::shared_ptr<IDevice>& device,
case Executor::FENCED: { case Executor::FENCED: {
SCOPED_TRACE("fenced"); SCOPED_TRACE("fenced");
ErrorStatus result = ErrorStatus::NONE; ErrorStatus result = ErrorStatus::NONE;
ndk::ScopedFileDescriptor syncFenceFd; FencedExecutionResult executionResult;
std::shared_ptr<IFencedExecutionCallback> fencedCallback;
auto ret = preparedModel->executeFenced(request, {}, testConfig.measureTiming, auto ret = preparedModel->executeFenced(request, {}, testConfig.measureTiming,
kNoDeadline, loopTimeoutDuration, kNoDuration, kNoDeadline, loopTimeoutDuration, kNoDuration,
&syncFenceFd, &fencedCallback); &executionResult);
ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC) ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
<< ret.getDescription(); << ret.getDescription();
if (!ret.isOk()) { if (!ret.isOk()) {
result = static_cast<ErrorStatus>(ret.getServiceSpecificError()); result = static_cast<ErrorStatus>(ret.getServiceSpecificError());
executionStatus = result; executionStatus = result;
} else if (syncFenceFd.get() != -1) { } else if (executionResult.syncFence.get() != -1) {
std::vector<ndk::ScopedFileDescriptor> waitFor; std::vector<ndk::ScopedFileDescriptor> waitFor;
auto dupFd = dup(syncFenceFd.get()); auto dupFd = dup(executionResult.syncFence.get());
ASSERT_NE(dupFd, -1); ASSERT_NE(dupFd, -1);
waitFor.emplace_back(dupFd); waitFor.emplace_back(dupFd);
// If a sync fence is returned, try start another run waiting for the sync fence. // If a sync fence is returned, try start another run waiting for the sync fence.
ret = preparedModel->executeFenced(request, waitFor, testConfig.measureTiming, ret = preparedModel->executeFenced(request, waitFor, testConfig.measureTiming,
kNoDeadline, loopTimeoutDuration, kNoDuration, kNoDeadline, loopTimeoutDuration, kNoDuration,
&syncFenceFd, &fencedCallback); &executionResult);
ASSERT_TRUE(ret.isOk()); ASSERT_TRUE(ret.isOk());
waitForSyncFence(syncFenceFd.get()); waitForSyncFence(executionResult.syncFence.get());
} }
if (result == ErrorStatus::NONE) { if (result == ErrorStatus::NONE) {
ASSERT_NE(fencedCallback, nullptr); ASSERT_NE(executionResult.callback, nullptr);
Timing timingFenced; Timing timingFenced;
auto ret = auto ret = executionResult.callback->getExecutionInfo(&timing, &timingFenced,
fencedCallback->getExecutionInfo(&timing, &timingFenced, &executionStatus); &executionStatus);
ASSERT_TRUE(ret.isOk()); ASSERT_TRUE(ret.isOk());
} }
break; break;

View File

@@ -198,8 +198,8 @@ class InvalidPreparedModel : public BnPreparedModel {
static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE)); static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
} }
ndk::ScopedAStatus executeFenced(const Request&, const std::vector<ndk::ScopedFileDescriptor>&, ndk::ScopedAStatus executeFenced(const Request&, const std::vector<ndk::ScopedFileDescriptor>&,
bool, int64_t, int64_t, int64_t, ndk::ScopedFileDescriptor*, bool, int64_t, int64_t, int64_t,
std::shared_ptr<IFencedExecutionCallback>*) override { FencedExecutionResult*) override {
return ndk::ScopedAStatus::fromServiceSpecificError( return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE)); static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
} }
@@ -893,25 +893,24 @@ class MemoryDomainExecutionTest
ErrorStatus executeFenced(const std::shared_ptr<IPreparedModel>& preparedModel, ErrorStatus executeFenced(const std::shared_ptr<IPreparedModel>& preparedModel,
const Request& request) { const Request& request) {
ndk::ScopedFileDescriptor syncFence; FencedExecutionResult executionResult;
std::shared_ptr<IFencedExecutionCallback> fencedCallback;
const auto ret = preparedModel->executeFenced(request, {}, false, kNoDeadline, const auto ret = preparedModel->executeFenced(request, {}, false, kNoDeadline,
kOmittedTimeoutDuration, kNoDuration, kOmittedTimeoutDuration, kNoDuration,
&syncFence, &fencedCallback); &executionResult);
if (!ret.isOk()) { if (!ret.isOk()) {
EXPECT_EQ(ret.getExceptionCode(), EX_SERVICE_SPECIFIC); EXPECT_EQ(ret.getExceptionCode(), EX_SERVICE_SPECIFIC);
return static_cast<ErrorStatus>(ret.getServiceSpecificError()); return static_cast<ErrorStatus>(ret.getServiceSpecificError());
} }
if (syncFence.get() != -1) { if (executionResult.syncFence.get() != -1) {
waitForSyncFence(syncFence.get()); waitForSyncFence(executionResult.syncFence.get());
} }
EXPECT_NE(fencedCallback, nullptr); EXPECT_NE(executionResult.callback, nullptr);
ErrorStatus executionStatus = ErrorStatus::GENERAL_FAILURE; ErrorStatus executionStatus = ErrorStatus::GENERAL_FAILURE;
Timing time = kNoTiming; Timing time = kNoTiming;
Timing timeFenced = kNoTiming; Timing timeFenced = kNoTiming;
const auto retExecutionInfo = const auto retExecutionInfo =
fencedCallback->getExecutionInfo(&time, &timeFenced, &executionStatus); executionResult.callback->getExecutionInfo(&time, &timeFenced, &executionStatus);
EXPECT_TRUE(retExecutionInfo.isOk()); EXPECT_TRUE(retExecutionInfo.isOk());
EXPECT_EQ(time, kNoTiming); EXPECT_EQ(time, kNoTiming);
return executionStatus; return executionStatus;

View File

@@ -68,11 +68,10 @@ static void validate(const std::shared_ptr<IPreparedModel>& preparedModel,
// fenced // fenced
{ {
SCOPED_TRACE(message + " [executeFenced]"); SCOPED_TRACE(message + " [executeFenced]");
ndk::ScopedFileDescriptor syncFence; FencedExecutionResult executionResult;
std::shared_ptr<IFencedExecutionCallback> callback;
const auto executeStatus = preparedModel->executeFenced(request, {}, false, kNoDeadline, const auto executeStatus = preparedModel->executeFenced(request, {}, false, kNoDeadline,
kOmittedTimeoutDuration, kOmittedTimeoutDuration,
kNoDuration, &syncFence, &callback); kNoDuration, &executionResult);
ASSERT_FALSE(executeStatus.isOk()); ASSERT_FALSE(executeStatus.isOk());
ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC); ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()), ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),