123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /*
- * Copyright 2022 Google LLC. All Rights Reserved.
- *
- * 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 "CapoDetector.h"
- #include <google/protobuf/message.h>
- #include <google/protobuf/io/coded_stream.h>
- #include <google/protobuf/io/zero_copy_stream_impl.h>
- #include <log/log.h>
- #ifdef LOG_TAG
- #undef LOG_TAG
- #define LOG_TAG "CapoDetector"
- #endif
- namespace android {
- namespace chre {
- namespace { // anonymous namespace for file-local definitions
- /**
- * Called when onConnected() to send NanoappList request.
- */
- void requestNanoappList(SocketClient &client) {
- flatbuffers::FlatBufferBuilder builder;
- HostProtocolHost::encodeNanoappListRequest(builder);
- if (!client.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
- ALOGE("Failed to send NanoappList request");
- }
- }
- } // namespace
- /**
- * Called when initializing connection with CHRE socket.
- */
- sp<CapoDetector> CapoDetector::start() {
- sp<CapoDetector> listener = new CapoDetector();
- if (!listener->connectInBackground(kChreSocketName, listener)) {
- ALOGE("Couldn't connect to CHRE socket");
- return nullptr;
- }
- ALOGI("%s connect to CHRE socket.", __func__);
- return listener;
- }
- /**
- * Called when the socket is successfully (re-)connected.
- * Reset the position and try to send NanoappList request.
- */
- void CapoDetector::onConnected() {
- flatbuffers::FlatBufferBuilder builder;
- // Reset the last position type.
- last_position_type_ = capo::PositionType::UNKNOWN;
- requestNanoappList(*this);
- }
- /**
- * Called when we have failed to (re-)connect the socket after many attempts
- * and are giving up.
- */
- void CapoDetector::onConnectionAborted() {
- ALOGE("%s, Capo Aborting Connection!", __func__);
- }
- /**
- * Invoked when the socket is disconnected, and this connection loss was not
- * the result of an explicit call to disconnect().
- * Reset the position while disconnecting.
- */
- void CapoDetector::onDisconnected() {
- last_position_type_ = capo::PositionType::UNKNOWN;
- }
- /**
- * Decode unix socket msgs to CHRE messages, and call the appropriate
- * callback depending on the CHRE message.
- */
- void CapoDetector::onMessageReceived(const void *data, size_t length) {
- if (!HostProtocolHost::decodeMessageFromChre(data, length, *this)) {
- ALOGE("Failed to decode message");
- }
- }
- /**
- * Listen for messages from capo nanoapp and handle the message.
- */
- void CapoDetector::handleNanoappMessage(const fbs::NanoappMessageT &message) {
- ALOGI("%s, Id %" PRIu64 ", type %d, size %d", __func__, message.app_id, message.message_type,
- static_cast<int>(message.message.size()));
- // Exclude the message with unmatched nanoapp id.
- if (message.app_id != kCapoNanoappId)
- return;
- // Handle the message with message_type.
- switch (message.message_type) {
- case capo::MessageType::ACK_NOTIFICATION: {
- capo::AckNotification gd;
- gd.set_notification_type(static_cast<capo::NotificationType>(message.message[1]));
- ALOGD("%s, get notification event from capo nanoapp, type %d", __func__,
- gd.notification_type());
- break;
- }
- case capo::MessageType::POSITION_DETECTED: {
- capo::PositionDetected gd;
- gd.set_position_type(static_cast<capo::PositionType>(message.message[1]));
- ALOGD("%s, get position event from capo nanoapp, type %d", __func__,
- gd.position_type());
- // Callback to function while getting carried position event.
- if (callback_func_ != nullptr) {
- last_position_type_ = gd.position_type();
- ALOGD("%s, sent position type %d to callback function", __func__,
- last_position_type_);
- callback_func_(last_position_type_);
- }
- break;
- }
- default:
- ALOGE("%s, get invalid message, type: %" PRIu32 ", from capo nanoapp.", __func__,
- message.message_type);
- break;
- }
- }
- /**
- * Handle the response of a NanoappList request.
- * Ensure that capo nanoapp is running.
- */
- void CapoDetector::handleNanoappListResponse(const fbs::NanoappListResponseT &response) {
- for (const std::unique_ptr<fbs::NanoappListEntryT> &nanoapp : response.nanoapps) {
- if (nanoapp->app_id == kCapoNanoappId) {
- if (nanoapp->enabled)
- enable();
- else
- ALOGE("Capo nanoapp not enabled");
- return;
- }
- }
- ALOGE("Capo nanoapp not found");
- }
- /**
- * Send enabling message to the nanoapp.
- */
- void CapoDetector::enable() {
- // Create CHRE message with serialized message
- flatbuffers::FlatBufferBuilder builder, config_builder, force_builder;
- auto config_data = std::make_unique<capo::ConfigureDetector_ConfigData>();
- auto msg = std::make_unique<capo::ConfigureDetector>();
- config_data->set_still_time_threshold_nanosecond(mCapoDetectorMDParameters.still_time_threshold_ns);
- config_data->set_window_width_nanosecond(mCapoDetectorMDParameters.window_width_ns);
- config_data->set_motion_confidence_threshold(mCapoDetectorMDParameters.motion_confidence_threshold);
- config_data->set_still_confidence_threshold(mCapoDetectorMDParameters.still_confidence_threshold);
- config_data->set_var_threshold(mCapoDetectorMDParameters.var_threshold);
- config_data->set_var_threshold_delta(mCapoDetectorMDParameters.var_threshold_delta);
- msg->set_allocated_config_data(config_data.release());
- auto pb_size = msg->ByteSizeLong();
- auto pb_data = std::make_unique<uint8_t[]>(pb_size);
- if (!msg->SerializeToArray(pb_data.get(), pb_size)) {
- ALOGE("Failed to serialize message.");
- }
- ALOGI("Configuring CapoDetector");
- // Configure the detector from host-side
- android::chre::HostProtocolHost::encodeNanoappMessage(
- config_builder, getNanoppAppId(), capo::MessageType::CONFIGURE_DETECTOR, getHostEndPoint(),
- pb_data.get(), pb_size);
- ALOGI("Sending capo config message to Nanoapp, %" PRIu32 " bytes", config_builder.GetSize());
- if (!sendMessage(config_builder.GetBufferPointer(), config_builder.GetSize())) {
- ALOGE("Failed to send config event for capo nanoapp");
- }
- ALOGI("Enabling CapoDetector");
- android::chre::HostProtocolHost::encodeNanoappMessage(
- builder, getNanoppAppId(), capo::MessageType::ENABLE_DETECTOR, getHostEndPoint(),
- /*messageData*/ nullptr, /*messageDataLenbuffer*/ 0);
- ALOGI("Sending enable message to Nanoapp, %" PRIu32 " bytes", builder.GetSize());
- if (!sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
- ALOGE("Failed to send enable event for capo nanoapp");
- }
- ALOGI("Forcing CapoDetector to update state");
- // Force an updated state upon connection
- android::chre::HostProtocolHost::encodeNanoappMessage(
- force_builder, getNanoppAppId(), capo::MessageType::FORCE_UPDATE, getHostEndPoint(),
- /*messageData*/ nullptr, /*messageDataLenbuffer*/ 0);
- ALOGI("Sending force-update message to Nanoapp, %" PRIu32 " bytes", force_builder.GetSize());
- if (!sendMessage(force_builder.GetBufferPointer(), force_builder.GetSize())) {
- ALOGE("Failed to send force-update event for capo nanoapp");
- }
- }
- } // namespace chre
- } // namespace android
|