Merge "Add HAL support for CHRE reliable messages" into main

This commit is contained in:
Matthew Sedam
2023-12-13 21:45:32 +00:00
committed by Android (Google) Code Review
15 changed files with 294 additions and 19 deletions

View File

@@ -45,4 +45,5 @@ parcelable ContextHubInfo {
byte chreApiMinorVersion;
char chrePatchVersion;
String[] supportedPermissions;
boolean supportsReliableMessages;
}

View File

@@ -39,4 +39,6 @@ parcelable ContextHubMessage {
int messageType;
byte[] messageBody;
String[] permissions;
boolean isReliable;
int messageSequenceNumber;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2023 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.contexthub;
@Backing(type="byte") @VintfStability
enum ErrorCode {
OK = 0,
TRANSIENT_ERROR,
PERMANENT_ERROR,
PERMISSION_DENIED,
DESTINATION_NOT_FOUND,
}

View File

@@ -48,5 +48,6 @@ interface IContextHub {
long[] getPreloadedNanoappIds(in int contextHubId);
void onNanSessionStateChanged(in android.hardware.contexthub.NanSessionStateUpdate update);
void setTestMode(in boolean enable);
void sendMessageDeliveryStatusToHub(in int contextHubId, in android.hardware.contexthub.MessageDeliveryStatus messageDeliveryStatus);
const int EX_CONTEXT_HUB_UNSPECIFIED = (-1) /* -1 */;
}

View File

@@ -39,6 +39,7 @@ interface IContextHubCallback {
void handleContextHubAsyncEvent(in android.hardware.contexthub.AsyncEventType evt);
void handleTransactionResult(in int transactionId, in boolean success);
void handleNanSessionRequest(in android.hardware.contexthub.NanSessionRequest request);
void handleMessageDeliveryStatus(in char hostEndpointId, in android.hardware.contexthub.MessageDeliveryStatus messageDeliveryStatus);
byte[16] getUuid();
String getName();
const int CONTEXTHUB_NAN_TRANSACTION_TIMEOUT_MS = 10000;

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2023 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.contexthub;
@VintfStability
parcelable MessageDeliveryStatus {
int messageSequenceNumber;
android.hardware.contexthub.ErrorCode errorCode;
}

View File

@@ -33,7 +33,9 @@ parcelable ContextHubInfo {
/** Peak MIPs this platform can deliver */
float peakMips;
/** The maximum length in bytes of the message that can be sent to the Context Hub. */
/**
* The maximum length in bytes of a message sent to the Context Hub.
*/
int maxSupportedMessageLengthBytes;
/**
@@ -61,4 +63,11 @@ parcelable ContextHubInfo {
* are granted in order to communicate with them.
*/
String[] supportedPermissions;
/**
* True if the Context Hub supports reliable messages. False otherwise, in which case
* ContextHubMessage.isReliable must always be set to false. See
* ContextHubMessage.isReliable for more information.
*/
boolean supportsReliableMessages;
}

View File

@@ -50,4 +50,35 @@ parcelable ContextHubMessage {
* of the permissions that the sending nanoapp is using.
*/
String[] permissions;
/**
* Whether the message is reliable.
*
* For reliable messages, the receiver is expected to acknowledge the reception of
* the message by sending a message delivery status back to the sender. Acknowledgment of
* the message must be returned within 1 second.
*
* For reliable messages sent by the host, the Context Hub invokes
* IContextHubCallback#handleMessageDeliveryStatus to report the status.
*
* For reliable messages sent by the Context Hub, the host calls
* IContextHub#sendMessageDeliveryStatusToHub to report the status.
*/
boolean isReliable;
/**
* The sequence number for a reliable message. For less than 2^32 messages, each message sent
* from a Context Hub will have a unique sequence number generated by the Context Hub, and the
* sequence numbers are guaranteed to not be reused for unacknowledged messages. For messages
* sent to the Context Hub, sequence numbers are only guaranteed to be unique within the scope
* of a given hostEndPoint. The sequence number may be reused if more than 2^32 messages are
* sent, due to the size limit of int.
*
* The sequence number is used only for reliable messages. There is no guarantee of strict
* ordering of messages. The recipient may receive messages with gaps between the sequence
* numbers. This is not an indication of a missed message.
*
* See isReliable for more information.
*/
int messageSequenceNumber;
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2023 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.contexthub;
@VintfStability
@Backing(type="byte")
enum ErrorCode {
/**
* No Error.
*/
OK = 0,
/**
* A generic transient error. The sender may retry the
* operation, but there is no guarantee of success.
*/
TRANSIENT_ERROR,
/**
* A generic permanent error. The sender should not retry the operation.
*/
PERMANENT_ERROR,
/**
* The request failed because the sender does not have necessary permissions.
* The sender should not retry the operation.
*/
PERMISSION_DENIED,
/**
* The request failed because the destination was not found.
* The sender should not retry the operation.
*/
DESTINATION_NOT_FOUND,
}

View File

@@ -20,6 +20,7 @@ import android.hardware.contexthub.ContextHubInfo;
import android.hardware.contexthub.ContextHubMessage;
import android.hardware.contexthub.HostEndpointInfo;
import android.hardware.contexthub.IContextHubCallback;
import android.hardware.contexthub.MessageDeliveryStatus;
import android.hardware.contexthub.NanSessionStateUpdate;
import android.hardware.contexthub.NanoappBinary;
import android.hardware.contexthub.NanoappInfo;
@@ -235,6 +236,21 @@ interface IContextHub {
*/
void setTestMode(in boolean enable);
/**
* Sends a message delivery status to the Context Hub in response to receiving a
* ContextHubMessage with isReliable=true. Each reliable message should have a
* messageDeliveryStatus response. This method sends the message delivery status
* back to the Context Hub.
*
* @param contextHubId The identifier of the Context Hub.
* @param messageDeliveryStatus The status to be sent.
*
* @throws EX_UNSUPPORTED_OPERATION if ContextHubInfo.supportsReliableMessages is false for
* this hub.
*/
void sendMessageDeliveryStatusToHub(
in int contextHubId, in MessageDeliveryStatus messageDeliveryStatus);
/**
* Error codes that are used as service specific errors with the AIDL return
* value EX_SERVICE_SPECIFIC.

View File

@@ -18,6 +18,7 @@ package android.hardware.contexthub;
import android.hardware.contexthub.AsyncEventType;
import android.hardware.contexthub.ContextHubMessage;
import android.hardware.contexthub.MessageDeliveryStatus;
import android.hardware.contexthub.NanSessionRequest;
import android.hardware.contexthub.NanoappInfo;
@@ -90,6 +91,19 @@ interface IContextHubCallback {
*/
void handleNanSessionRequest(in NanSessionRequest request);
/**
* This callback is passed by the Contexthub service to the HAL
* implementation to allow the HAL to send the response for a reliable message.
* The response is the message delivery status of a recently sent message. See
* sendMessageDeliveryStatusToHub() for more details.
*
* @param hostEndPointId The ID of the host endpoint associated with this message delivery
* status.
* @param messageDeliveryStatus The status to be sent.
*/
void handleMessageDeliveryStatus(
in char hostEndpointId, in MessageDeliveryStatus messageDeliveryStatus);
/**
* This callback is passed to the HAL implementation to allow the HAL to request a UUID that
* uniquely identifies a client.

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2023 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.contexthub;
import android.hardware.contexthub.ErrorCode;
@VintfStability
parcelable MessageDeliveryStatus {
/**
* The messageSequenceNumber of the ContextHubMessage to which this status applies.
*/
int messageSequenceNumber;
/**
* The error code associated with this status.
*/
ErrorCode errorCode;
}

View File

@@ -16,10 +16,7 @@
#include "contexthub-impl/ContextHub.h"
namespace aidl {
namespace android {
namespace hardware {
namespace contexthub {
namespace aidl::android::hardware::contexthub {
using ::ndk::ScopedAStatus;
@@ -34,10 +31,11 @@ ScopedAStatus ContextHub::getContextHubs(std::vector<ContextHubInfo>* out_contex
hub.chrePlatformId = UINT64_C(0x476f6f6754000000);
hub.chreApiMajorVersion = 1;
hub.chreApiMinorVersion = 6;
hub.supportsReliableMessages = false;
out_contextHubInfos->push_back(hub);
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
// We don't expose any nanoapps for the default impl, therefore all nanoapp-related APIs fail.
@@ -63,14 +61,14 @@ ScopedAStatus ContextHub::enableNanoapp(int32_t /* in_contextHubId */, int64_t /
}
ScopedAStatus ContextHub::onSettingChanged(Setting /* in_setting */, bool /*in_enabled */) {
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::queryNanoapps(int32_t in_contextHubId) {
if (in_contextHubId == kMockHubId && mCallback != nullptr) {
std::vector<NanoappInfo> nanoapps;
mCallback->handleNanoappInfo(nanoapps);
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
} else {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
@@ -85,18 +83,18 @@ ScopedAStatus ContextHub::getPreloadedNanoappIds(int32_t /* in_contextHubId */,
for (uint64_t i = 0; i < 10; ++i) {
out_preloadedNanoappIds->push_back(i);
}
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::onNanSessionStateChanged(const NanSessionStateUpdate& /*in_update*/) {
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::registerCallback(int32_t in_contextHubId,
const std::shared_ptr<IContextHubCallback>& in_cb) {
if (in_contextHubId == kMockHubId) {
mCallback = in_cb;
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
} else {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
@@ -108,20 +106,20 @@ ScopedAStatus ContextHub::sendMessageToHub(int32_t in_contextHubId,
// Return true here to indicate that the HAL has accepted the message.
// Successful delivery of the message to a nanoapp should be handled at
// a higher level protocol.
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
} else {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
}
ScopedAStatus ContextHub::setTestMode(bool /* enable */) {
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::onHostEndpointConnected(const HostEndpointInfo& in_info) {
mConnectedHostEndpoints.insert(in_info.hostEndpointId);
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::onHostEndpointDisconnected(char16_t in_hostEndpointId) {
@@ -129,10 +127,13 @@ ScopedAStatus ContextHub::onHostEndpointDisconnected(char16_t in_hostEndpointId)
mConnectedHostEndpoints.erase(in_hostEndpointId);
}
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
} // namespace contexthub
} // namespace hardware
} // namespace android
} // namespace aidl
ScopedAStatus ContextHub::sendMessageDeliveryStatusToHub(
int32_t /* in_contextHubId */,
const MessageDeliveryStatus& /* in_messageDeliveryStatus */) {
return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
} // namespace aidl::android::hardware::contexthub

View File

@@ -49,6 +49,9 @@ class ContextHub : public BnContextHub {
::ndk::ScopedAStatus onHostEndpointDisconnected(char16_t in_hostEndpointId) override;
::ndk::ScopedAStatus onNanSessionStateChanged(const NanSessionStateUpdate& in_update) override;
::ndk::ScopedAStatus sendMessageDeliveryStatusToHub(
int32_t in_contextHubId,
const MessageDeliveryStatus& in_messageDeliveryStatus) override;
private:
static constexpr uint32_t kMockHubId = 0;

View File

@@ -36,9 +36,11 @@ using ::android::binder::Status;
using ::android::hardware::contexthub::AsyncEventType;
using ::android::hardware::contexthub::ContextHubInfo;
using ::android::hardware::contexthub::ContextHubMessage;
using ::android::hardware::contexthub::ErrorCode;
using ::android::hardware::contexthub::HostEndpointInfo;
using ::android::hardware::contexthub::IContextHub;
using ::android::hardware::contexthub::IContextHubCallbackDefault;
using ::android::hardware::contexthub::MessageDeliveryStatus;
using ::android::hardware::contexthub::NanoappBinary;
using ::android::hardware::contexthub::NanoappInfo;
using ::android::hardware::contexthub::NanoappRpcService;
@@ -132,6 +134,12 @@ class EmptyContextHubCallback : public android::hardware::contexthub::BnContextH
return Status::ok();
}
Status handleMessageDeliveryStatus(
char16_t /* hostEndPointId */,
const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
return Status::ok();
}
Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
*out_uuid = kUuid;
return Status::ok();
@@ -172,6 +180,12 @@ class QueryAppsCallback : public android::hardware::contexthub::BnContextHubCall
return Status::ok();
}
Status handleMessageDeliveryStatus(
char16_t /* hostEndPointId */,
const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
return Status::ok();
}
Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
*out_uuid = kUuid;
return Status::ok();
@@ -248,6 +262,12 @@ class TransactionResultCallback : public android::hardware::contexthub::BnContex
return Status::ok();
}
Status handleMessageDeliveryStatus(
char16_t /* hostEndPointId */,
const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
return Status::ok();
}
Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
*out_uuid = kUuid;
return Status::ok();
@@ -431,6 +451,20 @@ TEST_P(ContextHubAidl, TestNanSessionStateChange) {
}
}
TEST_P(ContextHubAidl, TestSendMessageDeliveryStatusToHub) {
MessageDeliveryStatus messageDeliveryStatus;
messageDeliveryStatus.messageSequenceNumber = 123;
messageDeliveryStatus.errorCode = ErrorCode::OK;
Status status = contextHub->sendMessageDeliveryStatusToHub(getHubId(), messageDeliveryStatus);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
} else {
EXPECT_TRUE(status.isOk());
}
}
std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param));
}