Home | History | Annotate | Download | only in sensorhal
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <cstdlib>
     18 #include <inttypes.h>
     19 
     20 #define LOG_TAG "ActivityRecognitionHAL"
     21 #include <utils/Log.h>
     22 
     23 #include <media/stagefright/foundation/ADebug.h>
     24 
     25 #include "activity.h"
     26 
     27 using namespace android;
     28 
     29 static const int kVersionMajor = 1;
     30 static const int kVersionMinor = 0;
     31 
     32 // The maximum delta between events at which point their timestamps are to be
     33 // considered equal.
     34 static const int64_t kEventTimestampThresholdNanos = 100000000; // 100ms.
     35 static const int64_t kMaxEventAgeNanos = 10000000000; // 10000ms.
     36 static const useconds_t kFlushDelayMicros = 10000; // 10ms.
     37 
     38 static const char *const kActivityList[] = {
     39     ACTIVITY_TYPE_IN_VEHICLE,
     40     ACTIVITY_TYPE_ON_BICYCLE,
     41     ACTIVITY_TYPE_WALKING,
     42     ACTIVITY_TYPE_RUNNING,
     43     ACTIVITY_TYPE_STILL,
     44     ACTIVITY_TYPE_TILTING
     45 };
     46 
     47 static const int kActivitySensorMap[ARRAY_SIZE(kActivityList)][2] = {
     48     { COMMS_SENSOR_ACTIVITY_IN_VEHICLE_START,
     49       COMMS_SENSOR_ACTIVITY_IN_VEHICLE_STOP, },
     50     { COMMS_SENSOR_ACTIVITY_ON_BICYCLE_START,
     51       COMMS_SENSOR_ACTIVITY_ON_BICYCLE_STOP, },
     52     { COMMS_SENSOR_ACTIVITY_WALKING_START,
     53       COMMS_SENSOR_ACTIVITY_WALKING_STOP, },
     54     { COMMS_SENSOR_ACTIVITY_RUNNING_START,
     55       COMMS_SENSOR_ACTIVITY_RUNNING_STOP, },
     56     { COMMS_SENSOR_ACTIVITY_STILL_START,
     57       COMMS_SENSOR_ACTIVITY_STILL_STOP, },
     58     { COMMS_SENSOR_ACTIVITY_TILTING,
     59       COMMS_SENSOR_ACTIVITY_TILTING, },
     60 };
     61 
     62 // The global ActivityContext singleton.
     63 static ActivityContext *gActivityContext = NULL;
     64 
     65 static int ActivityClose(struct hw_device_t *) {
     66     ALOGI("close_activity");
     67     delete gActivityContext;
     68     gActivityContext = NULL;
     69     return 0;
     70 }
     71 
     72 static void RegisterActivityCallbackWrapper(
     73         const struct activity_recognition_device *,
     74         const activity_recognition_callback_procs_t *callback) {
     75     gActivityContext->registerActivityCallback(callback);
     76 }
     77 
     78 static int EnableActivityEventWrapper(
     79         const struct activity_recognition_device *,
     80         uint32_t activity_handle,
     81         uint32_t event_type,
     82         int64_t max_batch_report_latency_ns) {
     83     return gActivityContext->enableActivityEvent(activity_handle, event_type,
     84                                                  max_batch_report_latency_ns);
     85 }
     86 
     87 static int DisableActivityEventWrapper(
     88         const struct activity_recognition_device *,
     89         uint32_t activity_handle,
     90         uint32_t event_type) {
     91     return gActivityContext->disableActivityEvent(activity_handle, event_type);
     92 }
     93 
     94 static int FlushWrapper(const struct activity_recognition_device *) {
     95     return gActivityContext->flush();
     96 }
     97 
     98 ActivityContext::ActivityContext(const struct hw_module_t *module)
     99     : mHubConnection(HubConnection::getInstance()),
    100       mCallback(NULL),
    101       mNewestPublishedEventIndexIsKnown(false),
    102       mNewestPublishedEventIndex(0),
    103       mNewestPublishedTimestamp(0),
    104       mOutstandingFlushEvents(0) {
    105     memset(&device, 0, sizeof(device));
    106 
    107     device.common.tag = HARDWARE_DEVICE_TAG;
    108     device.common.version = ACTIVITY_RECOGNITION_API_VERSION_0_1;
    109     device.common.module = const_cast<hw_module_t *>(module);
    110     device.common.close = ActivityClose;
    111     device.register_activity_callback = RegisterActivityCallbackWrapper;
    112     device.enable_activity_event = EnableActivityEventWrapper;
    113     device.disable_activity_event = DisableActivityEventWrapper;
    114     device.flush = FlushWrapper;
    115 
    116     if (getHubAlive()) {
    117         mHubConnection->setActivityCallback(this);
    118 
    119         // Reset the system to a known good state by disabling all transitions.
    120         for (int i = COMMS_SENSOR_ACTIVITY_FIRST;
    121                 i <= COMMS_SENSOR_ACTIVITY_LAST; i++) {
    122             mHubConnection->queueActivate(i, false /* enable */);
    123         }
    124     }
    125 }
    126 
    127 ActivityContext::~ActivityContext() {
    128     mHubConnection->setActivityCallback(NULL);
    129 }
    130 
    131 /*
    132  * Obtain the activity handle for a given activity sensor index.
    133  */
    134 static int GetActivityHandleFromSensorIndex(int sensorIndex) {
    135     int normalizedSensorIndex = sensorIndex - COMMS_SENSOR_ACTIVITY_FIRST;
    136     return normalizedSensorIndex / 2;
    137 }
    138 
    139 /*
    140  * Obtain the activity type for a given activity sensor index.
    141  */
    142 static int GetActivityTypeFromSensorIndex(int sensorIndex) {
    143     int normalizedSensorIndex = sensorIndex - COMMS_SENSOR_ACTIVITY_FIRST;
    144     return (normalizedSensorIndex % 2) + 1;
    145 }
    146 
    147 void ActivityContext::PublishUnpublishedEvents() {
    148     if (mUnpublishedEvents.empty()) {
    149         return;
    150     }
    151 
    152     while (mUnpublishedEvents.size() > 0) {
    153         bool eventWasPublished = false;
    154 
    155         for (size_t i = 0; i < mUnpublishedEvents.size(); i++) {
    156             const ActivityEvent *event = &mUnpublishedEvents[i];
    157             if (event->eventIndex == (uint8_t)(mNewestPublishedEventIndex + 1)) {
    158                 PublishEvent(*event);
    159                 eventWasPublished = true;
    160                 mUnpublishedEvents.removeAt(i);
    161                 break;
    162             }
    163         }
    164 
    165         if (!eventWasPublished) {
    166             ALOGD("Waiting on unpublished events");
    167             break;
    168         }
    169     }
    170 }
    171 
    172 void ActivityContext::PublishEvent(const ActivityEvent& event) {
    173     activity_event_t halEvent;
    174     memset(&halEvent, 0, sizeof(halEvent));
    175 
    176     int64_t timestampDelta = event.whenNs - mNewestPublishedTimestamp;
    177     if (std::abs(timestampDelta) > kEventTimestampThresholdNanos) {
    178       mNewestPublishedTimestamp = event.whenNs;
    179     }
    180 
    181     halEvent.activity = GetActivityHandleFromSensorIndex(event.sensorIndex);
    182     halEvent.timestamp = mNewestPublishedTimestamp;
    183 
    184     if (event.sensorIndex == COMMS_SENSOR_ACTIVITY_TILTING) {
    185         ALOGD("Publishing tilt event (enter/exit)");
    186 
    187         // Publish two events (enter/exit) for TILTING events.
    188         halEvent.event_type = ACTIVITY_EVENT_ENTER;
    189         (*mCallback->activity_callback)(mCallback, &halEvent, 1);
    190 
    191         halEvent.event_type = ACTIVITY_EVENT_EXIT;
    192     } else {
    193         ALOGD("Publishing event - activity_handle: %d, event_type: %d"
    194               ", timestamp: %" PRIu64,
    195               halEvent.activity, halEvent.event_type, halEvent.timestamp);
    196 
    197         // Just a single event is required for all other activity types.
    198         halEvent.event_type = GetActivityTypeFromSensorIndex(event.sensorIndex);
    199     }
    200 
    201     (*mCallback->activity_callback)(mCallback, &halEvent, 1);
    202     mNewestPublishedEventIndex = event.eventIndex;
    203     mNewestPublishedEventIndexIsKnown = true;
    204 }
    205 
    206 void ActivityContext::DiscardExpiredUnpublishedEvents(uint64_t whenNs) {
    207     // Determine the current oldest buffered event.
    208     uint64_t oldestEventTimestamp = UINT64_MAX;
    209     for (size_t i = 0; i < mUnpublishedEvents.size(); i++) {
    210         const ActivityEvent *event = &mUnpublishedEvents[i];
    211         if (event->whenNs < oldestEventTimestamp) {
    212             oldestEventTimestamp = event->whenNs;
    213         }
    214     }
    215 
    216     // If the age of the oldest buffered event is too large an AR sample
    217     // has been lost. When this happens all AR transitions are set to
    218     // ACTIVITY_EVENT_EXIT and the event ordering logic is reset.
    219     if (oldestEventTimestamp != UINT64_MAX
    220         && (whenNs - oldestEventTimestamp) > kMaxEventAgeNanos) {
    221         ALOGD("Lost event detected, discarding buffered events");
    222 
    223         // Publish stop events for all activity types except for TILTING.
    224         for (uint32_t activity = 0;
    225              activity < (ARRAY_SIZE(kActivityList) - 1); activity++) {
    226             activity_event_t halEvent;
    227             memset(&halEvent, 0, sizeof(halEvent));
    228 
    229             halEvent.activity = activity;
    230             halEvent.timestamp = oldestEventTimestamp;
    231             halEvent.event_type = ACTIVITY_EVENT_EXIT;
    232             (*mCallback->activity_callback)(mCallback, &halEvent, 1);
    233         }
    234 
    235         // Reset the event reordering logic.
    236         OnSensorHubReset();
    237     }
    238 }
    239 
    240 void ActivityContext::OnActivityEvent(int sensorIndex, uint8_t eventIndex,
    241                                       uint64_t whenNs) {
    242     ALOGD("OnActivityEvent sensorIndex = %d, eventIndex = %" PRIu8
    243           ", whenNs = %" PRIu64, sensorIndex, eventIndex, whenNs);
    244 
    245     Mutex::Autolock autoLock(mCallbackLock);
    246     if (!mCallback) {
    247         return;
    248     }
    249 
    250     DiscardExpiredUnpublishedEvents(whenNs);
    251 
    252     ActivityEvent event = {
    253         .eventIndex = eventIndex,
    254         .sensorIndex = sensorIndex,
    255         .whenNs = whenNs,
    256     };
    257 
    258     if (!mNewestPublishedEventIndexIsKnown
    259             || eventIndex == (uint8_t)(mNewestPublishedEventIndex + 1)) {
    260         PublishEvent(event);
    261         PublishUnpublishedEvents();
    262     } else {
    263         ALOGD("OnActivityEvent out of order, pushing back");
    264         mUnpublishedEvents.push(event);
    265     }
    266 }
    267 
    268 void ActivityContext::OnFlush() {
    269     // Once the number of outstanding flush events has reached zero, publish an
    270     // event via the AR HAL.
    271     Mutex::Autolock autoLock(mCallbackLock);
    272     if (!mCallback) {
    273         return;
    274     }
    275 
    276     // For each flush event from the sensor hub, decrement the counter of
    277     // outstanding flushes.
    278     mOutstandingFlushEvents--;
    279     if (mOutstandingFlushEvents > 0) {
    280         ALOGV("OnFlush with %d outstanding flush events", mOutstandingFlushEvents);
    281         return;
    282     } else if (mOutstandingFlushEvents < 0) {
    283         // This can happen on app start.
    284         ALOGD("more flush events received than requested");
    285         mOutstandingFlushEvents = 0;
    286     }
    287 
    288     activity_event_t ev = {
    289         .event_type = ACTIVITY_EVENT_FLUSH_COMPLETE,
    290         .activity = 0,
    291         .timestamp = 0ll,
    292     };
    293 
    294     (*mCallback->activity_callback)(mCallback, &ev, 1);
    295     ALOGD("OnFlush published");
    296 }
    297 
    298 void ActivityContext::OnSensorHubReset() {
    299     // Reset the unpublished event queue and clear the last known published
    300     // event index.
    301     mUnpublishedEvents.clear();
    302     mNewestPublishedEventIndexIsKnown = false;
    303     mOutstandingFlushEvents = 0;
    304     mNewestPublishedTimestamp = 0;
    305 }
    306 
    307 void ActivityContext::registerActivityCallback(
    308         const activity_recognition_callback_procs_t *callback) {
    309     ALOGI("registerActivityCallback");
    310 
    311     Mutex::Autolock autoLock(mCallbackLock);
    312     mCallback = callback;
    313 }
    314 
    315 /*
    316  * Returns a sensor index for a given activity handle and transition type.
    317  */
    318 int GetActivitySensorForHandleAndType(uint32_t activity_handle,
    319                                       uint32_t event_type) {
    320     // Ensure that the requested activity index is valid.
    321     if (activity_handle >= ARRAY_SIZE(kActivityList)) {
    322         return 0;
    323     }
    324 
    325     // Ensure that the event type is either an ENTER or EXIT.
    326     if (event_type < ACTIVITY_EVENT_ENTER || event_type > ACTIVITY_EVENT_EXIT) {
    327         return 0;
    328     }
    329 
    330     return kActivitySensorMap[activity_handle][event_type - 1];
    331 }
    332 
    333 int ActivityContext::enableActivityEvent(uint32_t activity_handle,
    334         uint32_t event_type, int64_t max_report_latency_ns) {
    335     ALOGI("enableActivityEvent - activity_handle: %" PRIu32
    336           ", event_type: %" PRIu32 ", latency: %" PRId64,
    337           activity_handle, event_type, max_report_latency_ns);
    338 
    339     int sensor_index = GetActivitySensorForHandleAndType(activity_handle,
    340                                                          event_type);
    341     if (sensor_index <= 0) {
    342         ALOGE("Enabling invalid activity_handle: %" PRIu32
    343               ", event_type: %" PRIu32, activity_handle, event_type);
    344         return 1;
    345     }
    346 
    347     mHubConnection->queueBatch(sensor_index, 1000000, max_report_latency_ns);
    348     mHubConnection->queueActivate(sensor_index, true /* enable */);
    349     return 0;
    350 }
    351 
    352 int ActivityContext::disableActivityEvent(uint32_t activity_handle,
    353                                           uint32_t event_type) {
    354     ALOGI("disableActivityEvent");
    355 
    356     // Obtain the sensor index for the requested activity and transition types.
    357     int sensor_index = kActivitySensorMap[activity_handle][event_type - 1];
    358     if (sensor_index > 0) {
    359         mHubConnection->queueActivate(sensor_index, false /* enable */);
    360     } else {
    361         ALOGE("Disabling invalid activity_handle: %" PRIu32
    362               ", event_type: %" PRIu32, activity_handle, event_type);
    363     }
    364 
    365     return 0;
    366 }
    367 
    368 int ActivityContext::flush() {
    369     {
    370         // Aquire a lock for the mOutstandingFlushEvents shared state. OnFlush
    371         // modifies this value as flush results are returned. Nested scope is
    372         // used here to control the lifecycle of the lock as OnFlush may be
    373         // invoked before this method returns.
    374         Mutex::Autolock autoLock(mCallbackLock);
    375         mOutstandingFlushEvents +=
    376             (COMMS_SENSOR_ACTIVITY_LAST - COMMS_SENSOR_ACTIVITY_FIRST) + 1;
    377     }
    378 
    379     // Flush all activity sensors.
    380     for (int i = COMMS_SENSOR_ACTIVITY_FIRST;
    381             i <= COMMS_SENSOR_ACTIVITY_LAST; i++) {
    382         mHubConnection->queueFlush(i);
    383         usleep(kFlushDelayMicros);
    384     }
    385 
    386     return 0;
    387 }
    388 
    389 bool ActivityContext::getHubAlive() {
    390     return mHubConnection->initCheck() == OK
    391         && mHubConnection->getAliveCheck() == OK;
    392 }
    393 
    394 ////////////////////////////////////////////////////////////////////////////////
    395 
    396 static int open_activity(
    397         const struct hw_module_t *module,
    398         const char *,
    399         struct hw_device_t **dev) {
    400     ALOGI("open_activity");
    401 
    402     gActivityContext = new ActivityContext(module);
    403     *dev = &gActivityContext->device.common;
    404     return 0;
    405 }
    406 
    407 static struct hw_module_methods_t activity_module_methods = {
    408     .open = open_activity
    409 };
    410 
    411 static int get_activity_list(struct activity_recognition_module *,
    412                              char const* const **activity_list) {
    413     ALOGI("get_activity_list");
    414 
    415     if (gActivityContext != NULL && gActivityContext->getHubAlive()) {
    416         *activity_list = kActivityList;
    417         return sizeof(kActivityList) / sizeof(kActivityList[0]);
    418     } else {
    419         *activity_list = {};
    420         return 0;
    421     }
    422 }
    423 
    424 struct activity_recognition_module HAL_MODULE_INFO_SYM = {
    425         .common = {
    426                 .tag = HARDWARE_MODULE_TAG,
    427                 .version_major = kVersionMajor,
    428                 .version_minor = kVersionMinor,
    429                 .id = ACTIVITY_RECOGNITION_HARDWARE_MODULE_ID,
    430                 .name = "Google Activity Recognition module",
    431                 .author = "Google",
    432                 .methods = &activity_module_methods,
    433                 .dso  = NULL,
    434                 .reserved = {0},
    435         },
    436         .get_supported_activities_list = get_activity_list,
    437 };
    438