Home | History | Annotate | Download | only in dynamic_sensor
      1 /*
      2  * Copyright (C) 2017 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 "BaseSensorObject.h"
     18 #include "ConnectionDetector.h"
     19 #include "DummyDynamicAccelDaemon.h"
     20 #include "DynamicSensorManager.h"
     21 
     22 #include <cutils/properties.h>
     23 #include <utils/Log.h>
     24 #include <utils/SystemClock.h>
     25 #include <utils/misc.h>
     26 
     27 #include <sys/socket.h>
     28 #include <netinet/in.h>
     29 #include <algorithm>            //std::max
     30 
     31 #define SYSPROP_PREFIX                  "dynamic_sensor.dummy"
     32 #define FILE_NAME_BASE                  "dummy_accel_file"
     33 #define FILE_NAME_REGEX                 ("^" FILE_NAME_BASE "[0-9]$")
     34 
     35 namespace android {
     36 namespace SensorHalExt {
     37 
     38 DummyDynamicAccelDaemon::DummyDynamicAccelDaemon(DynamicSensorManager& manager)
     39         : BaseDynamicSensorDaemon(manager) {
     40     char property[PROPERTY_VALUE_MAX+1];
     41 
     42     property_get(SYSPROP_PREFIX ".file", property, "");
     43     if (strcmp(property, "") != 0) {
     44         mFileDetector = new FileConnectionDetector(
     45                 this, std::string(property), std::string(FILE_NAME_REGEX));
     46     }
     47 
     48     property_get(SYSPROP_PREFIX ".socket", property, "");
     49     if (strcmp(property, "") != 0) {
     50         mSocketDetector = new SocketConnectionDetector(this, atoi(property));
     51     }
     52 }
     53 
     54 BaseSensorVector DummyDynamicAccelDaemon::createSensor(const std::string &deviceKey) {
     55     BaseSensorVector ret;
     56     if (deviceKey.compare(0, 1, "/") == 0) {
     57         // file detector result, deviceKey is file absolute path
     58         const size_t len = ::strlen(FILE_NAME_BASE) + 1; // +1 for number
     59         if (deviceKey.length() < len) {
     60             ALOGE("illegal file device key %s", deviceKey.c_str());
     61         } else {
     62             size_t start = deviceKey.length() - len;
     63             ret.emplace_back(new DummySensor(deviceKey.substr(start)));
     64         }
     65     } else if (deviceKey.compare(0, ::strlen("socket:"), "socket:") == 0) {
     66         ret.emplace_back(new DummySensor(deviceKey));
     67     } else {
     68         // unknown deviceKey
     69         ALOGE("unknown deviceKey: %s", deviceKey.c_str());
     70     }
     71     return ret;
     72 }
     73 
     74 DummyDynamicAccelDaemon::DummySensor::DummySensor(const std::string &name)
     75         : Thread(false /*canCallJava*/), mRunState(false) {
     76     mSensorName = "Dummy Accel - " + name;
     77     // fake sensor information for dummy sensor
     78     mSensor = (struct sensor_t) {
     79         mSensorName.c_str(),
     80         "DemoSense, Inc.",
     81         1,                                         // version
     82         -1,                                        // handle, dummy number here
     83         SENSOR_TYPE_ACCELEROMETER,
     84         9.8 * 8.0f,                                // maxRange
     85         9.8 * 8.0f / 32768.0f,                     // resolution
     86         0.5f,                                      // power
     87         (int32_t)(1.0E6f / 50),                    // minDelay
     88         0,                                         // fifoReservedEventCount
     89         0,                                         // fifoMaxEventCount
     90         SENSOR_STRING_TYPE_ACCELEROMETER,
     91         "",                                        // requiredPermission
     92         (long)(1.0E6f / 50),                       // maxDelay
     93         SENSOR_FLAG_CONTINUOUS_MODE,
     94         { NULL, NULL }
     95     };
     96     mRunLock.lock();
     97     run("DummySensor");
     98 }
     99 
    100 DummyDynamicAccelDaemon::DummySensor::~DummySensor() {
    101     requestExitAndWait();
    102     // unlock mRunLock so thread can be unblocked
    103     mRunLock.unlock();
    104 }
    105 
    106 const sensor_t* DummyDynamicAccelDaemon::DummySensor::getSensor() const {
    107     return &mSensor;
    108 }
    109 
    110 void DummyDynamicAccelDaemon::DummySensor::getUuid(uint8_t* uuid) const {
    111     // at maximum, there will be always one instance, so we can hardcode
    112     size_t hash = std::hash<std::string>()(mSensorName);
    113     memset(uuid, 'x', 16);
    114     memcpy(uuid, &hash, sizeof(hash));
    115 }
    116 
    117 int DummyDynamicAccelDaemon::DummySensor::enable(bool enable) {
    118     std::lock_guard<std::mutex> lk(mLock);
    119     if (mRunState != enable) {
    120         if (enable) {
    121             mRunLock.unlock();
    122         } else {
    123             mRunLock.lock();
    124         }
    125         mRunState = enable;
    126     }
    127     return 0;
    128 }
    129 
    130 int DummyDynamicAccelDaemon::DummySensor::batch(int64_t /*samplePeriod*/, int64_t /*batchPeriod*/) {
    131     // Dummy sensor does not support changing rate and batching. But return successful anyway.
    132     return 0;
    133 }
    134 
    135 void DummyDynamicAccelDaemon::DummySensor::waitUntilNextSample() {
    136     // block when disabled (mRunLock locked)
    137     mRunLock.lock();
    138     mRunLock.unlock();
    139 
    140     if (!Thread::exitPending()) {
    141         // sleep 20 ms (50Hz)
    142         usleep(20000);
    143     }
    144 }
    145 
    146 bool DummyDynamicAccelDaemon::DummySensor::threadLoop() {
    147     // designated intialization will leave the unspecified fields zeroed
    148     sensors_event_t event = {
    149         .version = sizeof(event),
    150         .sensor = -1,
    151         .type = SENSOR_TYPE_ACCELEROMETER,
    152     };
    153 
    154     int64_t startTimeNs = elapsedRealtimeNano();
    155 
    156     ALOGI("Dynamic Dummy Accel started for sensor %s", mSensorName.c_str());
    157     while (!Thread::exitPending()) {
    158         waitUntilNextSample();
    159 
    160         if (Thread::exitPending()) {
    161             break;
    162         }
    163         int64_t nowTimeNs = elapsedRealtimeNano();
    164         float t = (nowTimeNs - startTimeNs) / 1e9f;
    165 
    166         event.data[0] = 2 * ::sin(3 * M_PI * t);
    167         event.data[1] = 3 * ::cos(3 * M_PI * t);
    168         event.data[2] = 1.5 * ::sin(6 * M_PI * t);
    169         event.timestamp = nowTimeNs;
    170         generateEvent(event);
    171     }
    172 
    173     ALOGI("Dynamic Dummy Accel thread ended for sensor %s", mSensorName.c_str());
    174     return false;
    175 }
    176 
    177 } // namespace SensorHalExt
    178 } // namespace android
    179 
    180