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 #define LOG_TAG "ActivityRecognitionHAL"
     18 //#define LOG_NDEBUG  0
     19 #include <utils/Log.h>
     20 
     21 #include "activity.h"
     22 
     23 #include <media/stagefright/foundation/ADebug.h>
     24 
     25 using namespace android;
     26 
     27 static const int kVersionMajor = 1;
     28 static const int kVersionMinor = 0;
     29 
     30 static const int ACTIVITY_TYPE_TILTING_INDEX = 6;
     31 
     32 static const char *const kActivityList[] = {
     33     ACTIVITY_TYPE_IN_VEHICLE,
     34     ACTIVITY_TYPE_ON_BICYCLE,
     35     ACTIVITY_TYPE_WALKING,
     36     ACTIVITY_TYPE_RUNNING,
     37     ACTIVITY_TYPE_STILL,
     38     "com.google.android.contexthub.ar.inconsistent",
     39     ACTIVITY_TYPE_TILTING
     40 };
     41 
     42 ActivityContext::ActivityContext(const struct hw_module_t *module)
     43     : mHubConnection(HubConnection::getInstance()),
     44       mHubAlive(true),
     45       mCallback(NULL),
     46       mPrevActivity(-1),
     47       mInitExitDone(false) {
     48     memset(&device, 0, sizeof(device));
     49 
     50     device.common.tag = HARDWARE_DEVICE_TAG;
     51     device.common.version = ACTIVITY_RECOGNITION_API_VERSION_0_1;
     52     device.common.module = const_cast<hw_module_t *>(module);
     53     device.common.close = CloseWrapper;
     54     device.register_activity_callback = RegisterActivityCallbackWrapper;
     55     device.enable_activity_event = EnableActivityEventWrapper;
     56     device.disable_activity_event = DisableActivityEventWrapper;
     57     device.flush = FlushWrapper;
     58 
     59     if (mHubConnection->initCheck() != (status_t)OK) {
     60         mHubAlive = false;
     61     } else {
     62         if (mHubConnection->getAliveCheck() != (status_t)OK) {
     63             mHubAlive = false;
     64         } else {
     65             mHubConnection->setActivityCallback(
     66                     this, &ActivityContext::HubCallbackWrapper);
     67 
     68             mHubConnection->queueActivate(COMMS_SENSOR_ACTIVITY, false /* enable */);
     69         }
     70     }
     71 }
     72 
     73 ActivityContext::~ActivityContext() {
     74     mHubConnection->setActivityCallback(NULL, NULL);
     75 }
     76 
     77 int ActivityContext::close() {
     78     ALOGI("close");
     79 
     80     delete this;
     81 
     82     return 0;
     83 }
     84 
     85 void ActivityContext::onActivityEvent(
     86         uint64_t when_us, bool is_flush, float x, float, float) {
     87     Mutex::Autolock autoLock(mLock);
     88 
     89     if (!mCallback) {
     90         return;
     91     }
     92 
     93     if (is_flush) {
     94         activity_event_t ev;
     95         memset(&ev, 0, sizeof(ev));
     96 
     97         ev.event_type = ACTIVITY_EVENT_FLUSH_COMPLETE;
     98         ev.activity = 0;
     99         ev.timestamp = 0ll;
    100 
    101         (*mCallback->activity_callback)(mCallback, &ev, 1);
    102         return;
    103     }
    104 
    105     int activityRaw = (int)x;
    106 
    107     ALOGV("activityRaw = %d", activityRaw);
    108 
    109     if (mPrevActivity >= 0 && mPrevActivity == activityRaw) {
    110         // same old, same old...
    111         return;
    112     }
    113 
    114     activity_event_t ev[8];
    115     memset(&ev, 0, 8*sizeof(activity_event_t));
    116     int num_events = 0;
    117 
    118     // exit all other activities when first enabled.
    119     if (!mInitExitDone) {
    120         mInitExitDone = true;
    121 
    122         int numActivities = sizeof(kActivityList) / sizeof(kActivityList[0]);
    123         for (int i = 0; i < numActivities; ++i) {
    124             if ((i == activityRaw) || !isEnabled(i, ACTIVITY_EVENT_EXIT)) {
    125                 continue;
    126             }
    127 
    128             activity_event_t *curr_ev = &ev[num_events];
    129             curr_ev->event_type = ACTIVITY_EVENT_EXIT;
    130             curr_ev->activity = i;
    131             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
    132             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
    133             num_events++;
    134         }
    135     }
    136 
    137     // tilt activities do not change the current activity type, but have a
    138     // simultaneous enter and exit event type
    139     if (activityRaw == ACTIVITY_TYPE_TILTING_INDEX) {
    140         if (isEnabled(activityRaw, ACTIVITY_EVENT_ENTER)) {
    141             activity_event_t *curr_ev = &ev[num_events];
    142             curr_ev->event_type = ACTIVITY_EVENT_ENTER;
    143             curr_ev->activity = activityRaw;
    144             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
    145             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
    146             num_events++;
    147         }
    148 
    149         if (isEnabled(activityRaw, ACTIVITY_EVENT_EXIT)) {
    150             activity_event_t *curr_ev = &ev[num_events];
    151             curr_ev->event_type = ACTIVITY_EVENT_EXIT;
    152             curr_ev->activity = activityRaw;
    153             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
    154             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
    155             num_events++;
    156         }
    157     } else {
    158         if ((mPrevActivity >= 0) &&
    159             (isEnabled(mPrevActivity, ACTIVITY_EVENT_EXIT))) {
    160             activity_event_t *curr_ev = &ev[num_events];
    161             curr_ev->event_type = ACTIVITY_EVENT_EXIT;
    162             curr_ev->activity = mPrevActivity;
    163             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
    164             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
    165             num_events++;
    166         }
    167 
    168         if (isEnabled(activityRaw, ACTIVITY_EVENT_ENTER)) {
    169             activity_event_t *curr_ev = &ev[num_events];
    170             curr_ev->event_type = ACTIVITY_EVENT_ENTER;
    171             curr_ev->activity = activityRaw;
    172             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
    173             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
    174             num_events++;
    175         }
    176 
    177         mPrevActivity = activityRaw;
    178     }
    179 
    180     if (num_events > 0) {
    181         (*mCallback->activity_callback)(mCallback, ev, num_events);
    182     }
    183 }
    184 
    185 void ActivityContext::registerActivityCallback(
    186         const activity_recognition_callback_procs_t *callback) {
    187     ALOGI("registerActivityCallback");
    188 
    189     Mutex::Autolock autoLock(mLock);
    190     mCallback = callback;
    191 }
    192 
    193 int ActivityContext::enableActivityEvent(
    194         uint32_t activity_handle,
    195         uint32_t event_type,
    196         int64_t max_batch_report_latency_ns) {
    197     ALOGI("enableActivityEvent");
    198 
    199     bool wasEnabled = !mMaxBatchReportLatencyNs.isEmpty();
    200     int64_t prev_latency = calculateReportLatencyNs();
    201 
    202     ALOGD_IF(DEBUG_ACTIVITY_RECOGNITION, "ACTVT type = %u, latency = %d sec", (unsigned) event_type,
    203           (int)(max_batch_report_latency_ns/1000000000ull));
    204 
    205     mMaxBatchReportLatencyNs.add(
    206             ((uint64_t)activity_handle << 32) | event_type,
    207             max_batch_report_latency_ns);
    208 
    209     if (!wasEnabled) {
    210         mPrevActivity = -1;
    211         mInitExitDone = false;
    212 
    213         mHubConnection->queueBatch(
    214             COMMS_SENSOR_ACTIVITY, SENSOR_FLAG_ON_CHANGE_MODE, 1000000, max_batch_report_latency_ns);
    215         mHubConnection->queueActivate(COMMS_SENSOR_ACTIVITY, true /* enable */);
    216     } else if (max_batch_report_latency_ns != prev_latency) {
    217         mHubConnection->queueBatch(
    218             COMMS_SENSOR_ACTIVITY, SENSOR_FLAG_ON_CHANGE_MODE, 1000000, max_batch_report_latency_ns);
    219     }
    220 
    221     return 0;
    222 }
    223 
    224 int64_t ActivityContext::calculateReportLatencyNs() {
    225     int64_t ret = INT64_MAX;
    226 
    227     for (size_t i = 0 ; i < mMaxBatchReportLatencyNs.size(); ++i) {
    228         if (mMaxBatchReportLatencyNs[i] <ret) {
    229             ret = mMaxBatchReportLatencyNs[i];
    230         }
    231     }
    232     return ret;
    233 }
    234 
    235 int ActivityContext::disableActivityEvent(
    236         uint32_t activity_handle, uint32_t event_type) {
    237     ALOGI("disableActivityEvent");
    238 
    239     bool wasEnabled = !mMaxBatchReportLatencyNs.isEmpty();
    240 
    241     mMaxBatchReportLatencyNs.removeItem(
    242             ((uint64_t)activity_handle << 32) | event_type);
    243 
    244     bool isEnabled = !mMaxBatchReportLatencyNs.isEmpty();
    245 
    246     if (wasEnabled && !isEnabled) {
    247         mHubConnection->queueActivate(COMMS_SENSOR_ACTIVITY, false /* enable */);
    248     }
    249 
    250     return 0;
    251 }
    252 
    253 bool ActivityContext::isEnabled(
    254         uint32_t activity_handle, uint32_t event_type) const {
    255     return mMaxBatchReportLatencyNs.indexOfKey(
    256             ((uint64_t)activity_handle << 32) | event_type) >= 0;
    257 }
    258 
    259 int ActivityContext::flush() {
    260     mHubConnection->queueFlush(COMMS_SENSOR_ACTIVITY);
    261     return 0;
    262 }
    263 
    264 // static
    265 int ActivityContext::CloseWrapper(struct hw_device_t *dev) {
    266     return reinterpret_cast<ActivityContext *>(dev)->close();
    267 }
    268 
    269 // static
    270 void ActivityContext::RegisterActivityCallbackWrapper(
    271         const struct activity_recognition_device *dev,
    272         const activity_recognition_callback_procs_t *callback) {
    273     const_cast<ActivityContext *>(
    274             reinterpret_cast<const ActivityContext *>(dev))
    275         ->registerActivityCallback(callback);
    276 }
    277 
    278 // static
    279 int ActivityContext::EnableActivityEventWrapper(
    280         const struct activity_recognition_device *dev,
    281         uint32_t activity_handle,
    282         uint32_t event_type,
    283         int64_t max_batch_report_latency_ns) {
    284     return const_cast<ActivityContext *>(
    285             reinterpret_cast<const ActivityContext *>(dev))
    286         ->enableActivityEvent(
    287             activity_handle, event_type, max_batch_report_latency_ns);
    288 }
    289 
    290 // static
    291 int ActivityContext::DisableActivityEventWrapper(
    292         const struct activity_recognition_device *dev,
    293         uint32_t activity_handle,
    294         uint32_t event_type) {
    295     return const_cast<ActivityContext *>(
    296             reinterpret_cast<const ActivityContext *>(dev))
    297         ->disableActivityEvent(activity_handle, event_type);
    298 }
    299 
    300 // static
    301 int ActivityContext::FlushWrapper(
    302         const struct activity_recognition_device *dev) {
    303     return const_cast<ActivityContext *>(
    304             reinterpret_cast<const ActivityContext *>(dev))->flush();
    305 }
    306 
    307 // static
    308 void ActivityContext::HubCallbackWrapper(
    309         void *me, uint64_t time_ms, bool is_flush, float x, float y, float z) {
    310     static_cast<ActivityContext *>(me)->onActivityEvent(time_ms, is_flush, x, y, z);
    311 }
    312 
    313 bool ActivityContext::getHubAlive() {
    314     return mHubAlive;
    315 }
    316 
    317 ////////////////////////////////////////////////////////////////////////////////
    318 
    319 static bool gHubAlive = false;
    320 
    321 static int open_activity(
    322         const struct hw_module_t *module,
    323         const char *,
    324         struct hw_device_t **dev) {
    325     ALOGI("open_activity");
    326 
    327     ActivityContext *ctx = new ActivityContext(module);
    328 
    329     gHubAlive = ctx->getHubAlive();
    330     *dev = &ctx->device.common;
    331 
    332     return 0;
    333 }
    334 
    335 static struct hw_module_methods_t activity_module_methods = {
    336     .open = open_activity
    337 };
    338 
    339 static int get_activity_list(
    340         struct activity_recognition_module *,
    341         char const* const **activity_list) {
    342     ALOGI("get_activity_list");
    343 
    344     if (gHubAlive) {
    345         *activity_list = kActivityList;
    346         return sizeof(kActivityList) / sizeof(kActivityList[0]);
    347     } else {
    348         *activity_list = {};
    349         return 0;
    350     }
    351 }
    352 
    353 struct activity_recognition_module HAL_MODULE_INFO_SYM = {
    354         .common = {
    355                 .tag = HARDWARE_MODULE_TAG,
    356                 .version_major = kVersionMajor,
    357                 .version_minor = kVersionMinor,
    358                 .id = ACTIVITY_RECOGNITION_HARDWARE_MODULE_ID,
    359                 .name = "Google Activity Recognition module",
    360                 .author = "Google",
    361                 .methods = &activity_module_methods,
    362                 .dso  = NULL,
    363                 .reserved = {0},
    364         },
    365         .get_supported_activities_list = get_activity_list,
    366 };
    367 
    368