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