Merge "Remove onSessionChanged in ImsMedia HAL" into main-ims-dev
diff --git a/automotive/remoteaccess/impl/default/client/Android.bp b/automotive/remoteaccess/hal/default/Android.bp
similarity index 94%
rename from automotive/remoteaccess/impl/default/client/Android.bp
rename to automotive/remoteaccess/hal/default/Android.bp
index 6327637..2502079 100644
--- a/automotive/remoteaccess/impl/default/client/Android.bp
+++ b/automotive/remoteaccess/hal/default/Android.bp
@@ -29,6 +29,7 @@
"RemoteAccessService",
],
shared_libs: [
+ "libbase",
"libbinder_ndk",
"liblog",
"libutils",
@@ -37,6 +38,7 @@
],
cflags: [
"-Wno-unused-parameter",
+ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
],
}
@@ -55,6 +57,7 @@
shared_libs: [
"libbase",
"libbinder_ndk",
+ "libcutils",
"liblog",
"libutils",
"libgrpc++",
diff --git a/automotive/remoteaccess/impl/default/client/include/RemoteAccessService.h b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
similarity index 74%
rename from automotive/remoteaccess/impl/default/client/include/RemoteAccessService.h
rename to automotive/remoteaccess/hal/default/include/RemoteAccessService.h
index 806440a..207c093 100644
--- a/automotive/remoteaccess/impl/default/client/include/RemoteAccessService.h
+++ b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
@@ -18,8 +18,11 @@
#include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteAccess.h>
+#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
#include <aidl/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.h>
#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+#include <utils/SystemClock.h>
#include <wakeup_client.grpc.pb.h>
#include <string>
@@ -30,6 +33,27 @@
namespace automotive {
namespace remoteaccess {
+// A IRemoteTaskCallback implementation for debug purpose.
+class DebugRemoteTaskCallback final
+ : public aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback {
+ public:
+ DebugRemoteTaskCallback() { mStartTimeMillis = android::uptimeMillis(); };
+
+ ndk::ScopedAStatus onRemoteTaskRequested(const std::string& clientId,
+ const std::vector<uint8_t>& data) override;
+ std::string printTasks();
+
+ private:
+ struct TaskData {
+ std::string clientId;
+ std::vector<uint8_t> data;
+ };
+
+ std::mutex mLock;
+ int64_t mStartTimeMillis;
+ std::vector<TaskData> mTasks;
+};
+
class RemoteAccessService
: public aidl::android::hardware::automotive::remoteaccess::BnRemoteAccess {
public:
@@ -51,10 +75,14 @@
ndk::ScopedAStatus notifyApStateChange(
const aidl::android::hardware::automotive::remoteaccess::ApState& newState) override;
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
private:
// For testing.
friend class RemoteAccessServiceUnitTest;
+ static bool checkDumpPermission();
+
WakeupClient::StubInterface* mGrpcStub;
std::thread mThread;
std::mutex mLock;
@@ -69,12 +97,14 @@
bool mTaskLoopRunning GUARDED_BY(mStartStopTaskLoopLock);
// Default wait time before retry connecting to remote access client is 10s.
size_t mRetryWaitInMs = 10'000;
+ std::shared_ptr<DebugRemoteTaskCallback> mDebugCallback;
void runTaskLoop();
void maybeStartTaskLoop();
void maybeStopTaskLoop();
void setRetryWaitInMs(size_t retryWaitInMs) { mRetryWaitInMs = retryWaitInMs; }
+ void dumpHelp(int fd);
};
} // namespace remoteaccess
diff --git a/automotive/remoteaccess/impl/default/proto/Android.bp b/automotive/remoteaccess/hal/default/proto/Android.bp
similarity index 100%
rename from automotive/remoteaccess/impl/default/proto/Android.bp
rename to automotive/remoteaccess/hal/default/proto/Android.bp
diff --git a/automotive/remoteaccess/impl/default/proto/wakeup_client.proto b/automotive/remoteaccess/hal/default/proto/wakeup_client.proto
similarity index 100%
rename from automotive/remoteaccess/impl/default/proto/wakeup_client.proto
rename to automotive/remoteaccess/hal/default/proto/wakeup_client.proto
diff --git a/automotive/remoteaccess/impl/default/client/remoteaccess-default-service.rc b/automotive/remoteaccess/hal/default/remoteaccess-default-service.rc
similarity index 100%
rename from automotive/remoteaccess/impl/default/client/remoteaccess-default-service.rc
rename to automotive/remoteaccess/hal/default/remoteaccess-default-service.rc
diff --git a/automotive/remoteaccess/impl/default/client/remoteaccess-default-service.xml b/automotive/remoteaccess/hal/default/remoteaccess-default-service.xml
similarity index 100%
rename from automotive/remoteaccess/impl/default/client/remoteaccess-default-service.xml
rename to automotive/remoteaccess/hal/default/remoteaccess-default-service.xml
diff --git a/automotive/remoteaccess/impl/default/client/src/RemoteAccessImpl.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
similarity index 70%
rename from automotive/remoteaccess/impl/default/client/src/RemoteAccessImpl.cpp
rename to automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
index 7431898..8720c2f 100644
--- a/automotive/remoteaccess/impl/default/client/src/RemoteAccessImpl.cpp
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
@@ -20,27 +20,35 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <grpcpp/create_channel.h>
+#include <stdlib.h>
#include <utils/Log.h>
+constexpr char SERVICE_NAME[] = "android.hardware.automotive.remoteaccess.IRemoteAccess/default";
+
int main(int /* argc */, char* /* argv */[]) {
ALOGI("Registering RemoteAccessService as service...");
- // TODO(b/241483300): Create GrpcClientStub here.
+#ifndef GRPC_SERVICE_ADDRESS
+ ALOGE("GRPC_SERVICE_ADDRESS is not defined, exiting");
+ exit(1);
+#endif
+ auto channel = grpc::CreateChannel(GRPC_SERVICE_ADDRESS, grpc::InsecureChannelCredentials());
+ auto clientStub = android::hardware::automotive::remoteaccess::WakeupClient::NewStub(channel);
auto service = ndk::SharedRefBase::make<
- android::hardware::automotive::remoteaccess::RemoteAccessService>(nullptr);
+ android::hardware::automotive::remoteaccess::RemoteAccessService>(clientStub.get());
- binder_exception_t err = AServiceManager_addService(
- service->asBinder().get(), "android.hardware.automotive.remote.IRemoteAccess/default");
+ binder_exception_t err = AServiceManager_addService(service->asBinder().get(), SERVICE_NAME);
if (err != EX_NONE) {
ALOGE("failed to register android.hardware.automotive.remote.IRemoteAccess service, "
"exception: %d",
err);
- return 1;
+ exit(1);
}
if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
ALOGE("%s", "failed to set thread pool max thread count");
- return 1;
+ exit(1);
}
ABinderProcess_startThreadPool();
diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
new file mode 100644
index 0000000..cc8b50c
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include "RemoteAccessService.h"
+
+#include <android-base/stringprintf.h>
+#include <android/binder_status.h>
+#include <grpc++/grpc++.h>
+#include <private/android_filesystem_config.h>
+#include <utils/Log.h>
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::remoteaccess::ApState;
+using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback;
+using ::android::base::ScopedLockAssertion;
+using ::android::base::StringAppendF;
+using ::android::base::StringPrintf;
+using ::grpc::ClientContext;
+using ::grpc::ClientReaderInterface;
+using ::grpc::Status;
+using ::grpc::StatusCode;
+using ::ndk::ScopedAStatus;
+
+const std::string WAKEUP_SERVICE_NAME = "com.google.vehicle.wakeup";
+constexpr char COMMAND_SET_AP_STATE[] = "--set-ap-state";
+constexpr char COMMAND_START_DEBUG_CALLBACK[] = "--start-debug-callback";
+constexpr char COMMAND_STOP_DEBUG_CALLBACK[] = "--stop-debug-callback";
+constexpr char COMMAND_SHOW_TASK[] = "--show-task";
+
+std::vector<uint8_t> stringToBytes(const std::string& s) {
+ const char* data = s.data();
+ return std::vector<uint8_t>(data, data + s.size());
+}
+
+ScopedAStatus rpcStatusToScopedAStatus(const Status& status, const std::string& errorMsg) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ status.error_code(), (errorMsg + ", error: " + status.error_message()).c_str());
+}
+
+std::string printBytes(const std::vector<uint8_t>& bytes) {
+ std::string s;
+ for (size_t i = 0; i < bytes.size(); i++) {
+ StringAppendF(&s, "%02x", bytes[i]);
+ }
+ return s;
+}
+
+bool checkBoolFlag(const char* flag) {
+ return !strcmp(flag, "1") || !strcmp(flag, "0");
+}
+
+} // namespace
+
+RemoteAccessService::RemoteAccessService(WakeupClient::StubInterface* grpcStub)
+ : mGrpcStub(grpcStub){};
+
+RemoteAccessService::~RemoteAccessService() {
+ maybeStopTaskLoop();
+}
+
+void RemoteAccessService::maybeStartTaskLoop() {
+ std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
+ if (mTaskLoopRunning) {
+ return;
+ }
+
+ mThread = std::thread([this]() { runTaskLoop(); });
+
+ mTaskLoopRunning = true;
+}
+
+void RemoteAccessService::maybeStopTaskLoop() {
+ std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
+ if (!mTaskLoopRunning) {
+ return;
+ }
+
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ // Try to stop the reading stream.
+ if (mGetRemoteTasksContext) {
+ mGetRemoteTasksContext->TryCancel();
+ mGetRemoteTasksContext.reset();
+ }
+ mTaskWaitStopped = true;
+ mCv.notify_all();
+ }
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+
+ mTaskLoopRunning = false;
+}
+
+void RemoteAccessService::runTaskLoop() {
+ GetRemoteTasksRequest request = {};
+ std::unique_ptr<ClientReaderInterface<GetRemoteTasksResponse>> reader;
+ while (true) {
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mGetRemoteTasksContext.reset(new ClientContext());
+ reader = mGrpcStub->GetRemoteTasks(mGetRemoteTasksContext.get(), request);
+ }
+ GetRemoteTasksResponse response;
+ while (reader->Read(&response)) {
+ ALOGI("Receiving one task from remote task client");
+
+ std::shared_ptr<IRemoteTaskCallback> callback;
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ callback = mRemoteTaskCallback;
+ }
+ if (callback == nullptr) {
+ ALOGD("No callback registered, task ignored");
+ continue;
+ }
+ ALOGD("Calling onRemoteTaskRequested callback for client ID: %s",
+ response.clientid().c_str());
+ ScopedAStatus callbackStatus = callback->onRemoteTaskRequested(
+ response.clientid(), stringToBytes(response.data()));
+ if (!callbackStatus.isOk()) {
+ ALOGE("Failed to call onRemoteTaskRequested callback, status: %d, message: %s",
+ callbackStatus.getStatus(), callbackStatus.getMessage());
+ }
+ }
+ Status status = reader->Finish();
+
+ ALOGE("GetRemoteTasks stream breaks, code: %d, message: %s, sleeping for 10s and retry",
+ status.error_code(), status.error_message().c_str());
+ // The long lasting connection should not return. But if the server returns, retry after
+ // 10s.
+ {
+ std::unique_lock lk(mLock);
+ if (mCv.wait_for(lk, std::chrono::milliseconds(mRetryWaitInMs), [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mTaskWaitStopped;
+ })) {
+ // If the stopped flag is set, we are quitting, exit the loop.
+ break;
+ }
+ }
+ }
+}
+
+ScopedAStatus RemoteAccessService::getDeviceId(std::string* deviceId) {
+ // TODO(b/241483300): Call VHAL to get VIN.
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::getWakeupServiceName(std::string* wakeupServiceName) {
+ *wakeupServiceName = WAKEUP_SERVICE_NAME;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::setRemoteTaskCallback(
+ const std::shared_ptr<IRemoteTaskCallback>& callback) {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mRemoteTaskCallback = callback;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::clearRemoteTaskCallback() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mRemoteTaskCallback.reset();
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::notifyApStateChange(const ApState& newState) {
+ ClientContext context;
+ NotifyWakeupRequiredRequest request = {};
+ request.set_iswakeuprequired(newState.isWakeupRequired);
+ NotifyWakeupRequiredResponse response = {};
+ Status status = mGrpcStub->NotifyWakeupRequired(&context, request, &response);
+ if (!status.ok()) {
+ return rpcStatusToScopedAStatus(status, "Failed to notify isWakeupRequired");
+ }
+
+ if (newState.isReadyForRemoteTask) {
+ maybeStartTaskLoop();
+ } else {
+ maybeStopTaskLoop();
+ }
+ return ScopedAStatus::ok();
+}
+
+bool RemoteAccessService::checkDumpPermission() {
+ uid_t uid = AIBinder_getCallingUid();
+ return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM;
+}
+
+void RemoteAccessService::dumpHelp(int fd) {
+ dprintf(fd, "%s",
+ (std::string("RemoteAccess HAL debug interface, Usage: \n") + COMMAND_SET_AP_STATE +
+ " [0/1](isReadyForRemoteTask) [0/1](isWakeupRequired) Set the new AP state\n" +
+ COMMAND_START_DEBUG_CALLBACK +
+ " Start a debug callback that will record the received tasks\n" +
+ COMMAND_STOP_DEBUG_CALLBACK + " Stop the debug callback\n" + COMMAND_SHOW_TASK +
+ " Show tasks received by debug callback\n")
+ .c_str());
+}
+
+binder_status_t RemoteAccessService::dump(int fd, const char** args, uint32_t numArgs) {
+ if (!checkDumpPermission()) {
+ dprintf(fd, "Caller must be root, system or shell\n");
+ return STATUS_PERMISSION_DENIED;
+ }
+
+ if (numArgs == 0) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+
+ if (!strcmp(args[0], COMMAND_SET_AP_STATE)) {
+ if (numArgs < 3) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ ApState apState = {};
+ const char* remoteTaskFlag = args[1];
+ if (!strcmp(remoteTaskFlag, "1") && !strcmp(remoteTaskFlag, "0")) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ if (!checkBoolFlag(args[1])) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ if (!strcmp(args[1], "1")) {
+ apState.isReadyForRemoteTask = true;
+ }
+ if (!checkBoolFlag(args[2])) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ if (!strcmp(args[2], "1")) {
+ apState.isWakeupRequired = true;
+ }
+ auto status = notifyApStateChange(apState);
+ if (!status.isOk()) {
+ dprintf(fd, "Failed to set AP state, code: %d, error: %s\n", status.getStatus(),
+ status.getMessage());
+ } else {
+ dprintf(fd, "successfully set the new AP state\n");
+ }
+ } else if (!strcmp(args[0], COMMAND_START_DEBUG_CALLBACK)) {
+ mDebugCallback = ndk::SharedRefBase::make<DebugRemoteTaskCallback>();
+ setRemoteTaskCallback(mDebugCallback);
+ dprintf(fd, "Debug callback registered\n");
+ } else if (!strcmp(args[0], COMMAND_STOP_DEBUG_CALLBACK)) {
+ if (mDebugCallback) {
+ mDebugCallback.reset();
+ }
+ clearRemoteTaskCallback();
+ dprintf(fd, "Debug callback unregistered\n");
+ } else if (!strcmp(args[0], COMMAND_SHOW_TASK)) {
+ if (mDebugCallback) {
+ dprintf(fd, "%s", mDebugCallback->printTasks().c_str());
+ } else {
+ dprintf(fd, "Debug callback is not currently used, use \"%s\" first.\n",
+ COMMAND_START_DEBUG_CALLBACK);
+ }
+ } else {
+ dumpHelp(fd);
+ }
+
+ return STATUS_OK;
+}
+
+ScopedAStatus DebugRemoteTaskCallback::onRemoteTaskRequested(const std::string& clientId,
+ const std::vector<uint8_t>& data) {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mTasks.push_back({
+ .clientId = clientId,
+ .data = data,
+ });
+ return ScopedAStatus::ok();
+}
+
+std::string DebugRemoteTaskCallback::printTasks() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ std::string s = StringPrintf("Received %zu tasks in %f seconds", mTasks.size(),
+ (android::uptimeMillis() - mStartTimeMillis) / 1000.);
+ for (size_t i = 0; i < mTasks.size(); i++) {
+ StringAppendF(&s, "Client Id: %s, Data: %s\n", mTasks[i].clientId.c_str(),
+ printBytes(mTasks[i].data).c_str());
+ }
+ return s;
+}
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/impl/default/test/Android.bp b/automotive/remoteaccess/hal/default/test/Android.bp
similarity index 98%
rename from automotive/remoteaccess/impl/default/test/Android.bp
rename to automotive/remoteaccess/hal/default/test/Android.bp
index e92440f..bf7d0b6 100644
--- a/automotive/remoteaccess/impl/default/test/Android.bp
+++ b/automotive/remoteaccess/hal/default/test/Android.bp
@@ -24,6 +24,7 @@
"RemoteAccessService",
],
shared_libs: [
+ "libbase",
"libbinder_ndk",
"liblog",
"libutils",
diff --git a/automotive/remoteaccess/impl/default/test/RemoteAccessServiceUnitTest.cpp b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
similarity index 100%
rename from automotive/remoteaccess/impl/default/test/RemoteAccessServiceUnitTest.cpp
rename to automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
diff --git a/automotive/remoteaccess/impl/default/client/src/RemoteAccessService.cpp b/automotive/remoteaccess/impl/default/client/src/RemoteAccessService.cpp
deleted file mode 100644
index 6b97840..0000000
--- a/automotive/remoteaccess/impl/default/client/src/RemoteAccessService.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-#include "RemoteAccessService.h"
-
-#include <android/binder_status.h>
-#include <grpc++/grpc++.h>
-#include <utils/Log.h>
-#include <chrono>
-#include <thread>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace remoteaccess {
-
-namespace {
-
-using ::aidl::android::hardware::automotive::remoteaccess::ApState;
-using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback;
-using ::android::base::ScopedLockAssertion;
-using ::grpc::ClientContext;
-using ::grpc::ClientReaderInterface;
-using ::grpc::Status;
-using ::grpc::StatusCode;
-using ::ndk::ScopedAStatus;
-
-const std::string WAKEUP_SERVICE_NAME = "com.google.vehicle.wakeup";
-
-std::vector<uint8_t> stringToBytes(const std::string& s) {
- const char* data = s.data();
- return std::vector<uint8_t>(data, data + s.size());
-}
-
-ScopedAStatus rpcStatusToScopedAStatus(const Status& status, const std::string& errorMsg) {
- return ScopedAStatus::fromServiceSpecificErrorWithMessage(
- status.error_code(), (errorMsg + ", error: " + status.error_message()).c_str());
-}
-
-} // namespace
-
-RemoteAccessService::RemoteAccessService(WakeupClient::StubInterface* grpcStub)
- : mGrpcStub(grpcStub){};
-
-RemoteAccessService::~RemoteAccessService() {
- maybeStopTaskLoop();
-}
-
-void RemoteAccessService::maybeStartTaskLoop() {
- std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
- if (mTaskLoopRunning) {
- return;
- }
-
- mThread = std::thread([this]() { runTaskLoop(); });
-
- mTaskLoopRunning = true;
-}
-
-void RemoteAccessService::maybeStopTaskLoop() {
- std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
- if (!mTaskLoopRunning) {
- return;
- }
-
- {
- std::lock_guard<std::mutex> lockGuard(mLock);
- // Try to stop the reading stream.
- if (mGetRemoteTasksContext) {
- mGetRemoteTasksContext->TryCancel();
- mGetRemoteTasksContext.reset();
- }
- mTaskWaitStopped = true;
- mCv.notify_all();
- }
- if (mThread.joinable()) {
- mThread.join();
- }
-
- mTaskLoopRunning = false;
-}
-
-void RemoteAccessService::runTaskLoop() {
- GetRemoteTasksRequest request = {};
- std::unique_ptr<ClientReaderInterface<GetRemoteTasksResponse>> reader;
- while (true) {
- {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mGetRemoteTasksContext.reset(new ClientContext());
- reader = mGrpcStub->GetRemoteTasks(mGetRemoteTasksContext.get(), request);
- }
- GetRemoteTasksResponse response;
- while (reader->Read(&response)) {
- std::shared_ptr<IRemoteTaskCallback> callback;
- {
- std::lock_guard<std::mutex> lockGuard(mLock);
- callback = mRemoteTaskCallback;
- }
- if (callback == nullptr) {
- continue;
- }
- ScopedAStatus callbackStatus = callback->onRemoteTaskRequested(
- response.clientid(), stringToBytes(response.data()));
- if (!callbackStatus.isOk()) {
- ALOGE("Failed to call onRemoteTaskRequested callback, status: %d, message: %s",
- callbackStatus.getStatus(), callbackStatus.getMessage());
- }
- }
- Status status = reader->Finish();
-
- ALOGE("GetRemoteTasks stream breaks, code: %d, message: %s, sleeping for 10s and retry",
- status.error_code(), status.error_message().c_str());
- // The long lasting connection should not return. But if the server returns, retry after
- // 10s.
- {
- std::unique_lock lk(mLock);
- if (mCv.wait_for(lk, std::chrono::milliseconds(mRetryWaitInMs), [this] {
- ScopedLockAssertion lockAssertion(mLock);
- return mTaskWaitStopped;
- })) {
- // If the stopped flag is set, we are quitting, exit the loop.
- break;
- }
- }
- }
-}
-
-ScopedAStatus RemoteAccessService::getDeviceId(std::string* deviceId) {
- // TODO(b/241483300): Call VHAL to get VIN.
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::getWakeupServiceName(std::string* wakeupServiceName) {
- *wakeupServiceName = WAKEUP_SERVICE_NAME;
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::setRemoteTaskCallback(
- [[maybe_unused]] const std::shared_ptr<IRemoteTaskCallback>& callback) {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mRemoteTaskCallback = callback;
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::clearRemoteTaskCallback() {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mRemoteTaskCallback.reset();
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::notifyApStateChange(const ApState& newState) {
- ClientContext context;
- NotifyWakeupRequiredRequest request = {};
- request.set_iswakeuprequired(newState.isWakeupRequired);
- NotifyWakeupRequiredResponse response = {};
- Status status = mGrpcStub->NotifyWakeupRequired(&context, request, &response);
- if (!status.ok()) {
- return rpcStatusToScopedAStatus(status, "Failed to notify isWakeupRequired");
- }
-
- if (newState.isReadyForRemoteTask) {
- maybeStartTaskLoop();
- } else {
- maybeStopTaskLoop();
- }
- return ScopedAStatus::ok();
-}
-
-} // namespace remoteaccess
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/remoteaccess/test_grpc_server/README.md b/automotive/remoteaccess/test_grpc_server/README.md
new file mode 100644
index 0000000..deea764
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/README.md
@@ -0,0 +1,7 @@
+# Test GRPC Server.
+
+A test GRPC server that implements wakeup_client.proto. This test server acts
+as a reference implementation for a remote wakeup client running on TCU. This
+reference server also implements wakeup_client_debug.proto which is the
+debugging interface. It is recommended that the actual implementation also
+implements this test interface for easier end-to-end testing.
diff --git a/automotive/remoteaccess/impl/default/test/Android.bp b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
similarity index 68%
copy from automotive/remoteaccess/impl/default/test/Android.bp
copy to automotive/remoteaccess/test_grpc_server/impl/Android.bp
index e92440f..5332c92 100644
--- a/automotive/remoteaccess/impl/default/test/Android.bp
+++ b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
@@ -12,32 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_test {
- name: "RemoteAccessServiceUnitTest",
+cc_binary {
+ name: "TestWakeupClientServer",
vendor: true,
- srcs: ["*.cpp"],
- whole_static_libs: [
- "RemoteAccessService",
- ],
+ srcs: ["src/*.cpp"],
+ local_include_dirs: ["include"],
shared_libs: [
- "libbinder_ndk",
+ "libbase",
"liblog",
"libutils",
"libgrpc++",
"libprotobuf-cpp-full",
],
- // libgrpc++.so is installed as root, require root to access it.
- require_root: true,
- static_libs: [
- "libgtest",
- "libgmock",
+ whole_static_libs: [
+ "wakeup_client_protos",
],
cflags: [
"-Wno-unused-parameter",
+ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
],
- test_suites: ["device-tests"],
}
diff --git a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
new file mode 100644
index 0000000..4c440b8
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <wakeup_client.grpc.pb.h>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <string>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+// A class to generate fake task for testing. Not required for real implementation. In real
+// implementation, the task should come from remote task server. This class is thread-safe.
+class FakeTaskGenerator final {
+ public:
+ GetRemoteTasksResponse generateTask();
+
+ private:
+ // Simulates the client ID for each task.
+ std::atomic<int> mCurrentClientId = 0;
+ constexpr static uint8_t DATA[] = {0xde, 0xad, 0xbe, 0xef};
+};
+
+// TaskQueue is thread-safe.
+class TaskQueue final {
+ public:
+ void add(const GetRemoteTasksResponse& response);
+ std::optional<GetRemoteTasksResponse> maybePopOne();
+ void waitForTask();
+ void stopWait();
+
+ private:
+ std::mutex mLock;
+ std::queue<GetRemoteTasksResponse> mTasks GUARDED_BY(mLock);
+ // A variable to notify mTasks is not empty.
+ std::condition_variable mTasksNotEmptyCv;
+ bool mStopped GUARDED_BY(mLock);
+};
+
+class TestWakeupClientServiceImpl final : public WakeupClient::Service {
+ public:
+ TestWakeupClientServiceImpl();
+
+ ~TestWakeupClientServiceImpl();
+
+ grpc::Status GetRemoteTasks(grpc::ServerContext* context, const GetRemoteTasksRequest* request,
+ grpc::ServerWriter<GetRemoteTasksResponse>* writer) override;
+
+ grpc::Status NotifyWakeupRequired(grpc::ServerContext* context,
+ const NotifyWakeupRequiredRequest* request,
+ NotifyWakeupRequiredResponse* response) override;
+
+ private:
+ // This is a thread for communicating with remote wakeup server (via network) and receive tasks
+ // from it.
+ std::thread mThread;
+ // A variable to notify server is stopping.
+ std::condition_variable mServerStoppedCv;
+ std::mutex mLock;
+ bool mServerStopped GUARDED_BY(mLock);
+
+ // Thread-safe. For test impl only.
+ FakeTaskGenerator mFakeTaskGenerator;
+ // Thread-sfae.
+ TaskQueue mTaskQueue;
+
+ void fakeTaskGenerateLoop();
+};
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
new file mode 100644
index 0000000..1eb87e2
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include "TestWakeupClientServiceImpl.h"
+
+#include <android-base/stringprintf.h>
+#include <utils/Log.h>
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+namespace {
+
+using ::android::base::ScopedLockAssertion;
+using ::android::base::StringPrintf;
+using ::grpc::ServerContext;
+using ::grpc::ServerWriter;
+using ::grpc::Status;
+
+constexpr int kTaskIntervalInSec = 5;
+
+} // namespace
+
+GetRemoteTasksResponse FakeTaskGenerator::generateTask() {
+ int clientId = mCurrentClientId++;
+ GetRemoteTasksResponse response;
+ response.set_data(std::string(reinterpret_cast<const char*>(DATA), sizeof(DATA)));
+ std::string clientIdStr = StringPrintf("%d", clientId);
+ response.set_clientid(clientIdStr);
+ return response;
+}
+
+std::optional<GetRemoteTasksResponse> TaskQueue::maybePopOne() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ if (mTasks.size() == 0) {
+ return std::nullopt;
+ }
+ GetRemoteTasksResponse response = mTasks.front();
+ mTasks.pop();
+ return std::move(response);
+}
+void TaskQueue::add(const GetRemoteTasksResponse& task) {
+ // TODO (b/246841306): add timeout to tasks.
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mTasks.push(task);
+ mTasksNotEmptyCv.notify_all();
+}
+
+void TaskQueue::waitForTask() {
+ std::unique_lock<std::mutex> lock(mLock);
+ mTasksNotEmptyCv.wait(lock, [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mTasks.size() > 0 || mStopped;
+ });
+}
+
+void TaskQueue::stopWait() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mStopped = true;
+ mTasksNotEmptyCv.notify_all();
+}
+
+TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() {
+ mThread = std::thread([this] { fakeTaskGenerateLoop(); });
+}
+
+TestWakeupClientServiceImpl::~TestWakeupClientServiceImpl() {
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mServerStopped = true;
+ mServerStoppedCv.notify_all();
+ }
+ mTaskQueue.stopWait();
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void TestWakeupClientServiceImpl::fakeTaskGenerateLoop() {
+ // In actual implementation, this should communicate with the remote server and receives tasks
+ // from it. Here we simulate receiving one remote task every {kTaskIntervalInSec}s.
+ while (true) {
+ mTaskQueue.add(mFakeTaskGenerator.generateTask());
+ ALOGI("Sleeping for %d seconds until next task", kTaskIntervalInSec);
+
+ std::unique_lock lk(mLock);
+ if (mServerStoppedCv.wait_for(lk, std::chrono::seconds(kTaskIntervalInSec), [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mServerStopped;
+ })) {
+ // If the stopped flag is set, we are quitting, exit the loop.
+ return;
+ }
+ }
+}
+
+Status TestWakeupClientServiceImpl::GetRemoteTasks(ServerContext* context,
+ const GetRemoteTasksRequest* request,
+ ServerWriter<GetRemoteTasksResponse>* writer) {
+ ALOGD("GetRemoteTasks called");
+ while (true) {
+ mTaskQueue.waitForTask();
+
+ while (true) {
+ auto maybeTask = mTaskQueue.maybePopOne();
+ if (!maybeTask.has_value()) {
+ // No task left, loop again and wait for another task(s).
+ break;
+ }
+ // Loop through all the task in the queue but obtain lock for each element so we don't
+ // hold lock while writing the response.
+ const GetRemoteTasksResponse& response = maybeTask.value();
+ if (!writer->Write(response)) {
+ // Broken stream, maybe the client is shutting down.
+ ALOGW("Failed to deliver remote task to remote access HAL");
+ // The task failed to be sent, add it back to the queue. The order might change, but
+ // it is okay.
+ mTaskQueue.add(response);
+ return Status::CANCELLED;
+ }
+ }
+ }
+ return Status::OK;
+}
+
+Status TestWakeupClientServiceImpl::NotifyWakeupRequired(ServerContext* context,
+ const NotifyWakeupRequiredRequest* request,
+ NotifyWakeupRequiredResponse* response) {
+ return Status::OK;
+}
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
new file mode 100644
index 0000000..bb03e70
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include <string>
+
+#include "TestWakeupClientServiceImpl.h"
+
+#include <grpc/grpc.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <utils/Log.h>
+
+using ::android::hardware::automotive::remoteaccess::TestWakeupClientServiceImpl;
+using ::grpc::Server;
+using ::grpc::ServerBuilder;
+using ::grpc::ServerWriter;
+
+void RunServer() {
+ std::string serverAddress(GRPC_SERVICE_ADDRESS);
+ std::shared_ptr<TestWakeupClientServiceImpl> service =
+ std::make_unique<TestWakeupClientServiceImpl>();
+
+ ServerBuilder builder;
+ builder.AddListeningPort(serverAddress, grpc::InsecureServerCredentials());
+ builder.RegisterService(service.get());
+ std::unique_ptr<Server> server(builder.BuildAndStart());
+ ALOGI("Test Remote Access GRPC Server listening on %s", serverAddress.c_str());
+ server->Wait();
+}
+
+int main(int argc, char** argv) {
+ RunServer();
+ return 0;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
index 7fab555..ea9f3a4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
@@ -36,9 +36,6 @@
interface IImsMediaSession {
oneway void setListener(in android.hardware.radio.ims.media.IImsMediaSessionListener sessionListener);
oneway void modifySession(in android.hardware.radio.ims.media.RtpConfig config);
- oneway void addConfig(in android.hardware.radio.ims.media.RtpConfig config);
- oneway void deleteConfig(in android.hardware.radio.ims.media.RtpConfig config);
- oneway void confirmConfig(in android.hardware.radio.ims.media.RtpConfig config);
oneway void sendDtmf(char dtmfDigit, int duration);
oneway void startDtmf(char dtmfDigit);
oneway void stopDtmf();
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
index d515ac8..f03b29e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
@@ -35,8 +35,6 @@
@VintfStability
interface IImsMediaSessionListener {
oneway void onModifySessionResponse(in android.hardware.radio.ims.media.RtpConfig config, android.hardware.radio.ims.media.RtpError error);
- oneway void onAddConfigResponse(in android.hardware.radio.ims.media.RtpConfig config, android.hardware.radio.ims.media.RtpError error);
- oneway void onConfirmConfigResponse(in android.hardware.radio.ims.media.RtpConfig config, android.hardware.radio.ims.media.RtpError error);
oneway void onFirstMediaPacketReceived(in android.hardware.radio.ims.media.RtpConfig config);
oneway void onHeaderExtensionReceived(in List<android.hardware.radio.ims.media.RtpHeaderExtension> extensions);
oneway void notifyMediaInactivity(android.hardware.radio.ims.media.MediaProtocolType packetType);
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
index d291f44..a8d2161 100644
--- a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
@@ -44,37 +44,6 @@
void modifySession(in RtpConfig config);
/**
- * Adds a new remote configuration to a RTP session during early media
- * scenarios where the IMS network could add more than one remote endpoint.
- *
- * @param config provides remote end point info and codec details
- */
- void addConfig(in RtpConfig config);
-
- /**
- * Deletes a remote configuration from a RTP session during early media
- * scenarios. A session shall have at least one config so this API shall
- * not delete the last config.
- *
- * @param config remote config to be deleted
- */
- void deleteConfig(in RtpConfig config);
-
- /**
- * Confirms a remote configuration for a Rtp session for early media scenarios
- * when there are more than one remote configs. All other early remote configs
- * (potentially including the config created as part of openSession) are auto
- * deleted when one config is confirmed.
- * Confirming a remote configuration is necessary only if additional
- * configurations were created.
- * New remote configurations cannot be added after a remote configuration is
- * confirmed.
- *
- * @param config remote config to be confirmed
- */
- void confirmConfig(in RtpConfig config);
-
- /**
* Send DTMF digit until the duration expires.
*
* @param dtmfDigit single char having one of 12 values: 0-9, *, #
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
index abf7fcd..d40da64 100644
--- a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
@@ -40,30 +40,6 @@
void onModifySessionResponse(in RtpConfig config, RtpError error);
/**
- * Notifies the result of IImsMediaSession#addConfig() API.
- *
- * @param config The RTP config passed in IImsMediaSession#addConfig() API
- * @param error RtpError.NONE in case of success else one of the following
- * RtpError :INVALID_PARAM
- * RtpError :INTERNAL_ERR
- * RtpError :NO_MEMORY
- * RtpError :NO_RESOURCES
- * RtpError :PORT_UNAVAILABLE
- */
- void onAddConfigResponse(in RtpConfig config, RtpError error);
-
- /**
- * Notifies the result of IImsMediaSession#confirmConfig() API.
- *
- * @param config The RtpConfig passed in IImsMediaSession#confirmConfig() API
- * @param error RtpError.NONE in case of success else one of the following
- * RtpError :INVALID_PARAM
- * RtpError :INTERNAL_ERR
- * RtpError :NO_RESOURCES
- */
- void onConfirmConfigResponse(in RtpConfig config, RtpError error);
-
- /**
* Indicates when the first Rtp media packet is received by the UE during ring
* back, call hold or early media scenarios. This is sent only if the packet is
* received on the active remote configuration.
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index 6954d65..6854851 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -49,8 +49,16 @@
* "security_level" : "tee" / "strongbox",
* "fused": 1 / 0, ; 1 if secure boot is enforced for the processor that the IRPC
* ; implementation is contained in. 0 otherwise.
- * "cert_type": "widevine" / "keymint"
+ * "cert_type": CertificateType;
* }
+ *
+ * ; A tstr identifying the type of certificate. The set of supported certificate types may
+ * ; be extended without requiring a version bump of the HAL. Custom certificate types may
+ * ; be used, but the provisioning server may reject the request for an unknown certificate
+ * ; type. The currently defined certificate types are:
+ * ; - "widevine"
+ * ; - "keymint"
+ * CertificateType = tstr
*/
byte[] deviceInfo;
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 926d105..2e4fc15 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -624,9 +624,15 @@
*
* o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
*
- * o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be less than
- * the current secure timestamp (which is a monotonic timer counting milliseconds since
- * boot.)
+ * o If the device has a source of secure time, then the timestamp in the auth token plus the
+ * value of the Tag::AUTH_TIMEOUT must be greater than the current secure timestamp (which
+ * is a monotonic timer counting milliseconds since boot).
+ *
+ * o If the device does not have a source of secure time, then the timestamp check should be
+ * performed on the first update(), updateAad() or finish() invocation for the operation,
+ * using the timeStampToken parameter provided on the invocation to indicate the current
+ * timestamp. It may optionally also be performed on subsequent update() / updateAad() /
+ * finish() invocations.
*
* If any of these conditions are not met, begin() must return
* ErrorCode::KEY_USER_NOT_AUTHENTICATED.
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index c30c183..82c8a0d 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -40,31 +40,7 @@
*
* == Authorization Enforcement ==
*
- * Key authorization enforcement is performed primarily in begin(). The one exception is the
- * case where the key has:
- *
- * o One or more Tag::USER_SECURE_IDs, and
- *
- * o Does not have a Tag::AUTH_TIMEOUT
- *
- * In this case, the key requires an authorization per operation, and the update method must
- * receive a non-null and valid HardwareAuthToken. For the auth token to be valid, all of the
- * following has to be true:
- *
- * o The HMAC field must validate correctly.
- *
- * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
- * the secure ID values in the token.
- *
- * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
- *
- * o The challenge field in the auth token must contain the value returned from
- * IKeyMintDevice::begin(), given by the challenge field of the BeginResult structure.
- *
- * If any of these conditions are not met, updateAad() must return
- * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
- *
- * The caller must provide the auth token on every call to updateAad(), update() and finish().
+ * See the Authorization Enforcement section for the update() method.
*
*
* For GCM encryption, the AEAD tag must be appended to the ciphertext by finish(). During
@@ -104,16 +80,22 @@
*
* == Authorization Enforcement ==
*
- * Key authorization enforcement is performed primarily in IKeyMintDevice::begin(). The one
- * exception is the case where the key has:
+ * Key authorization enforcement is performed primarily in IKeyMintDevice::begin(). There are
+ * two exceptions to this:
*
- * o One or more Tag::USER_SECURE_IDs, and
+ * 1) Key with USER_SECURE_IDs but no AUTH_TIMEOUT
*
- * o Does not have a Tag::AUTH_TIMEOUT
+ * 2) Key with USER_SECURE_IDs and AUTH_TIMEOUT, but the device does not support secure time.
*
- * In this case, the key requires an authorization per operation, and the update method must
- * receive a non-empty and valid HardwareAuthToken. For the auth token to be valid, all of the
- * following has to be true:
+ * The first exception is the case where the key:
+ *
+ * o Has one or more Tag::USER_SECURE_IDs, and
+ *
+ * o Does not have a Tag::AUTH_TIMEOUT
+ *
+ * In this case, the key requires an authorization per operation, and update() / updateAad() /
+ * finish() methods must receive a non-null and valid HardwareAuthToken. For the auth token to
+ * be valid, all of the following has to be true:
*
* o The HMAC field must validate correctly.
*
@@ -125,10 +107,47 @@
* o The challenge field in the auth token must contain the challenge value contained in the
* BeginResult returned from IKeyMintDevice::begin().
*
- * If any of these conditions are not met, update() must return
+ * If any of these conditions are not met, the method must return
* ErrorCode::KEY_USER_NOT_AUTHENTICATED.
*
- * The caller must provide the auth token on every call to update() and finish().
+ * The caller must provide the auth token on every call to update(), updateAad() and finish().
+ *
+ *
+ * The second exception is the case where the key:
+ *
+ * o Has one or more Tag::USER_SECURE_IDs, and
+ *
+ * o Has a Tag::AUTH_TIMEOUT value, but the device does not have a source of secure time (as
+ * indicated by the KeyMintHardwareInfo.timestampTokenRequired field).
+ *
+ * In this case, the key requires an per-operation authorization on the first call to update(),
+ * updateAad() or finish() for the operation, using the provided timeStampToken as a source of
+ * secure time. For this timeStampToken to be valid, all of the following has to be true:
+ *
+ * o The HMAC field must validate correctly.
+ *
+ * o The challenge field in the auth token must contain the challenge value contained in the
+ * BeginResult returned from IKeyMintDevice::begin().
+ *
+ * The resulting secure time value is then used to authenticate the HardwareAuthToken. For the
+ * auth token to be valid, all of the following has to be true:
+ *
+ * o The HMAC field must validate correctly.
+ *
+ * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+ * the secure ID values in the token.
+ *
+ * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+ *
+ * o The challenge field in the auth token must contain the challenge value contained in the
+ * BeginResult returned from IKeyMintDevice::begin().
+ *
+ * o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be greater
+ * than the provided secure timestamp.
+
+ * If any of these conditions are not met, the method must return
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
*
* -- RSA keys --
*
@@ -187,24 +206,7 @@
* Key authorization enforcement is performed primarily in begin(). The exceptions are
* authorization per operation keys and confirmation-required keys.
*
- * Authorization per operation keys are the case where the key has one or more
- * Tag::USER_SECURE_IDs, and does not have a Tag::AUTH_TIMEOUT. In this case, the key requires
- * an authorization per operation, and the finish method must receive a non-empty and valid
- * authToken. For the auth token to be valid, all of the following has to be true:
- *
- * o The HMAC field must validate correctly.
- *
- * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
- * the secure ID values in the token.
- *
- * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
- *
- * o The challenge field in the auth token must contain the operation challenge.
- *
- * If any of these conditions are not met, update() must return
- * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
- *
- * The caller must provide the auth token on every call to update() and finish().
+ * Authorization per operation keys must be authorized as described for the update() method.
*
* Confirmation-required keys are keys that were generated with
* Tag::TRUSTED_CONFIRMATION_REQUIRED. For these keys, when doing a signing operation the
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index c2acbed..3f1f2f7 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -151,7 +151,8 @@
/**
* This method has been removed in version 3 of the HAL. The header is kept around for
- * backwards compatibility purposes. Calling this method should return STATUS_REMOVED on v3.
+ * backwards compatibility purposes. From v3, this method should raise a
+ * ServiceSpecificException with an error code of STATUS_REMOVED.
*
* For v1 and v2 implementations:
* generateCertificateRequest creates a certificate request to be sent to the provisioning
@@ -378,8 +379,8 @@
* ; Last certificate corresponds to KeyMint's DICE key.
* ]
*
- * ; This is the signed payload for each entry in the DCC. Note that the "Configuration
- * ; Input Values" described by the Open Profile are not used here. Instead, the Dcc
+ * ; This is the signed payload for each entry in the DICE chain. Note that the "Configuration
+ * ; Input Values" described by the Open Profile are not used here. Instead, the DICE chain
* ; defines its own configuration values for the Configuration Descriptor field. See
* ; the Open Profile for DICE for more details on the fields. SHA256 and SHA512 are acceptable
* ; hash algorithms. The digest bstr values in the payload are the digest values without any
@@ -408,8 +409,8 @@
* -4670551 : bstr, ; Mode
* }
*
- * ; Each entry in the Dcc is a DiceChainEntryPayload signed by the key from the previous entry
- * ; in the Dcc array.
+ * ; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
+ * ; entry in the DICE chain array.
* DiceChainEntry = [ ; COSE_Sign1 (untagged)
* protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
* unprotected: {},
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
index 00cae32..671cd85 100644
--- a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
+++ b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
@@ -37,10 +37,8 @@
"libutils",
],
sanitize: {
- address: true,
undefined: true,
all_undefined: true,
- fuzzer: true,
cfi: true,
integer_overflow: true,
scs: true,