Merge "Dynamic sensor manager module - framework"

This commit is contained in:
Peng Xu 2017-03-10 22:21:30 +00:00 committed by Android (Google) Code Review
commit e12a0cc39d
11 changed files with 1111 additions and 0 deletions

View file

@ -0,0 +1,77 @@
# Copyright (C) 2017 The Android Open Source Project
#
# 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.
LOCAL_PATH := $(call my-dir)
COMMON_CFLAGS := -Wall -Werror -Wextra
#
# There are two ways to utilize the dynamic sensor module:
# 1. Use as an extension in an existing hal: declare dependency on libdynamic_sensor_ext shared
# library in existing sensor hal.
# 2. Use as a standalone sensor HAL and configure multihal to combine it with sensor hal that
# hosts other sensors: add dependency on sensors.dynamic_sensor_hal in device level makefile and
# write multihal configuration file accordingly.
#
# Please take only one of these two options to avoid conflict over hardware resource.
#
#
# Option 1: sensor extension module
#
include $(CLEAR_VARS)
LOCAL_MODULE := libdynamic_sensor_ext
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_OWNER := google
LOCAL_CFLAGS += $(COMMON_CFLAGS) -DLOG_TAG=\"DynamicSensorExt\"
LOCAL_SRC_FILES := \
BaseSensorObject.cpp \
DynamicSensorManager.cpp \
RingBuffer.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
liblog
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
#
# Option 2: independent sensor hal
#
include $(CLEAR_VARS)
LOCAL_MODULE := sensors.dynamic_sensor_hal
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_OWNER := google
LOCAL_CFLAGS += $(COMMON_CFLAGS) -DLOG_TAG=\"DynamicSensorHal\"
LOCAL_SRC_FILES := \
BaseSensorObject.cpp \
DynamicSensorManager.cpp \
RingBuffer.cpp \
sensors.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
liblog \
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
#ifndef ANDROID_SENSORHAL_EXT_BASE_DYNAMIC_SENSOR_DAEMON_H
#define ANDROID_SENSORHAL_EXT_BASE_DYNAMIC_SENSOR_DAEMON_H
#include <utils/RefBase.h>
namespace android {
namespace SensorHalExt {
class DynamicSensorManager;
class BaseDynamicSensorDaemon : public RefBase {
public:
BaseDynamicSensorDaemon(DynamicSensorManager& manager) : mManager(manager) {}
virtual ~BaseDynamicSensorDaemon() = default;
protected:
DynamicSensorManager& mManager;
};
} // namespace SensorHalExt
} // namespace android
#endif // ANDROID_SENSORHAL_EXT_BASE_DYNAMIC_SENSOR_DAEMON_H

View file

@ -0,0 +1,60 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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 "BaseSensorObject.h"
#include "SensorEventCallback.h"
#include <utils/Log.h>
#include <cstring>
namespace android {
namespace SensorHalExt {
BaseSensorObject::BaseSensorObject() : mCallback(nullptr) {
}
bool BaseSensorObject::setEventCallback(SensorEventCallback* callback) {
if (mCallback != nullptr) {
ALOGE("callback is already assigned, cannot change.");
return false;
}
mCallback = callback;
return true;
}
void BaseSensorObject::getUuid(uint8_t* uuid) const {
// default uuid denoting uuid feature is not supported on this sensor.
memset(uuid, 0, 16);
}
int BaseSensorObject::flush() {
static const sensors_event_t event = {
.type = SENSOR_TYPE_META_DATA,
.timestamp = TIMESTAMP_AUTO_FILL // timestamp will be filled at dispatcher
};
generateEvent(event);
return 0;
}
void BaseSensorObject::generateEvent(const sensors_event_t &e) {
if (mCallback) {
mCallback->submitEvent(this, e);
}
}
} // namespace SensorHalExt
} // namespace android

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
#ifndef ANDROID_SENSORHAL_BASE_SENSOR_OBJECT_H
#define ANDROID_SENSORHAL_BASE_SENSOR_OBJECT_H
#include <utils/RefBase.h>
#include <utils/Timers.h> // for nsecs_t
#include <cstdint>
struct sensor_t;
struct sensors_event_t;
namespace android {
namespace SensorHalExt {
class SensorEventCallback;
class BaseSensorObject : virtual public RefBase {
public:
BaseSensorObject();
virtual ~BaseSensorObject() = default;
// always called by DynamicSensorManager, callback must point to
// valid object throughout life cycle of BaseSensorObject
bool setEventCallback(SensorEventCallback* callback);
// virtual functions to get sensor information and operate sensor
virtual const sensor_t* getSensor() const = 0;
// get uuid of sensor, default implementation set it to all zero, means does not have a uuid.
virtual void getUuid(uint8_t* uuid) const;
// enable sensor
virtual int enable(bool enable) = 0;
// set sample period and batching period of sensor.
virtual int batch(nsecs_t samplePeriod, nsecs_t batchPeriod) = 0;
// flush sensor, default implementation will send a flush complete event back.
virtual int flush();
protected:
// utility function for sub-class
void generateEvent(const sensors_event_t &e);
private:
SensorEventCallback* mCallback;
};
} // namespace SensorHalExt
} // namespace android
#endif // ANDROID_SENSORHAL_BASE_SENSOR_OBJECT_H

View file

@ -0,0 +1,283 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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 "BaseDynamicSensorDaemon.h"
#include "BaseSensorObject.h"
#include "DynamicSensorManager.h"
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <cassert>
namespace android {
namespace SensorHalExt {
DynamicSensorManager* DynamicSensorManager::createInstance(
int handleBase, int handleCount, SensorEventCallback *callback) {
auto m = new DynamicSensorManager(handleBase, handleBase + handleCount - 1, callback);
return m;
}
DynamicSensorManager::DynamicSensorManager(
int handleBase, int handleMax, SensorEventCallback* callback) :
mHandleRange(handleBase, handleMax),
mCallback(callback),
mFifo(callback ? 0 : kFifoSize),
mNextHandle(handleBase+1) {
assert(handleBase > 0 && handleMax > handleBase + 1); // handleBase is reserved
mMetaSensor = (const sensor_t) {
"Dynamic Sensor Manager",
"Google",
1, // version
handleBase, // handle
SENSOR_TYPE_DYNAMIC_SENSOR_META,
1, // maxRange
1, // resolution
1e-6f, // power, very small number instead of 0
// to avoid sigularity in app
(int32_t)(1000), // minDelay
0, // fifoReservedEventCount
0, // fifoMaxEventCount
SENSOR_STRING_TYPE_DYNAMIC_SENSOR_META,
"", // requiredPermission
(long)(1000), // maxDelay
SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP,
{ NULL, NULL }
};
}
DynamicSensorManager::~DynamicSensorManager() {
// free all daemons first
mDaemonVector.clear();
}
bool DynamicSensorManager::owns(int handle) const {
return handle >= mHandleRange.first && handle < mHandleRange.second;
}
int DynamicSensorManager::activate(int handle, bool enable) {
if (handle == mHandleRange.first) {
// ignored
return 0;
}
// in case there is a pending report, now it is time to remove it as it is no longer necessary.
{
std::lock_guard<std::mutex> lk(mLock);
mPendingReport.erase(handle);
}
return operateSensor(handle,
[&enable] (sp<BaseSensorObject> s)->int {
return s->enable(enable);
});
}
int DynamicSensorManager::batch(int handle, nsecs_t sample_period, nsecs_t batch_period) {
if (handle == mHandleRange.first) {
// ignored
return 0;
}
return operateSensor(handle,
[&sample_period, &batch_period] (sp<BaseSensorObject> s)->int {
return s->batch(sample_period, batch_period);
});
}
int DynamicSensorManager::setDelay(int handle, nsecs_t sample_period) {
return batch(handle, sample_period, 0);
}
int DynamicSensorManager::flush(int handle) {
if (handle == mHandleRange.first) {
// TODO: submit a flush complete here
static const sensors_event_t event = {
.type = SENSOR_TYPE_META_DATA,
.sensor = mHandleRange.first,
.timestamp = TIMESTAMP_AUTO_FILL, // timestamp will be filled at dispatcher
};
submitEvent(nullptr, event);
return 0;
}
return operateSensor(handle, [] (sp<BaseSensorObject> s)->int {return s->flush();});
}
int DynamicSensorManager::poll(sensors_event_t * data, int count) {
assert(mCallback == nullptr);
std::lock_guard<std::mutex> lk(mFifoLock);
return mFifo.read(data, count);
}
bool DynamicSensorManager::registerSensor(sp<BaseSensorObject> sensor) {
std::lock_guard<std::mutex> lk(mLock);
if (mReverseMap.find(sensor.get()) != mReverseMap.end()) {
ALOGE("trying to add the same sensor twice, ignore");
return false;
}
int handle = getNextAvailableHandle();
if (handle < 0) {
ALOGE("Running out of handle, quit.");
return false;
}
// these emplace will always be successful
mMap.emplace(handle, sensor);
mReverseMap.emplace(sensor.get(), handle);
sensor->setEventCallback(this);
auto entry = mPendingReport.emplace(
std::piecewise_construct,
std::forward_as_tuple(handle),
std::forward_as_tuple(handle, sensor));
if (entry.second) {
submitEvent(nullptr, entry.first->second.generateConnectionEvent(mHandleRange.first));
}
return entry.second;
}
void DynamicSensorManager::unregisterSensor(sp<BaseSensorObject> sensor) {
std::lock_guard<std::mutex> lk(mLock);
auto i = mReverseMap.find(sensor.get());
if (i == mReverseMap.end()) {
ALOGE("cannot remove a non-exist sensor");
return;
}
int handle = i->second;
mReverseMap.erase(i);
mMap.erase(handle);
// will not clean up mPendingReport here, it will be cleaned up when at first activate call.
// sensorservice is guranteed to call activate upon arrival of dynamic sensor meta connection
// event.
// send disconnection event
sensors_event_t event;
ConnectionReport::fillDisconnectionEvent(&event, mHandleRange.first, handle);
submitEvent(nullptr, event);
}
int DynamicSensorManager::submitEvent(sp<BaseSensorObject> source, const sensors_event_t &e) {
int handle;
if (source == nullptr) {
handle = mHandleRange.first;
} else {
std::lock_guard<std::mutex> lk(mLock);
auto i = mReverseMap.find(source.get());
if (i == mReverseMap.end()) {
ALOGE("cannot submit event for sensor that has not been registered");
return NAME_NOT_FOUND;
}
handle = i->second;
}
// making a copy of events, prepare for editing
sensors_event_t event = e;
event.version = sizeof(event);
// special case of flush complete
if (event.type == SENSOR_TYPE_META_DATA) {
event.sensor = 0;
event.meta_data.sensor = handle;
} else {
event.sensor = handle;
}
// set timestamp if it is default value
if (event.timestamp == TIMESTAMP_AUTO_FILL) {
event.timestamp = elapsedRealtimeNano();
}
if (mCallback) {
// extention mode, calling callback directly
int ret;
ret = mCallback->submitEvent(nullptr, event);
if (ret < 0) {
ALOGE("DynamicSensorManager callback failed, ret: %d", ret);
}
} else {
// standalone mode, add event to internal buffer for poll() to pick up
std::lock_guard<std::mutex> lk(mFifoLock);
if (mFifo.write(&event, 1) < 0) {
ALOGE("DynamicSensorManager fifo full");
}
}
return 0;
}
int DynamicSensorManager::getNextAvailableHandle() {
if (mNextHandle == mHandleRange.second) {
return -1;
}
return mNextHandle++;
}
const sensor_t& DynamicSensorManager::getDynamicMetaSensor() const {
return mMetaSensor;
}
DynamicSensorManager::ConnectionReport::ConnectionReport(
int handle, sp<BaseSensorObject> sensor) :
mSensor(*(sensor->getSensor())),
mName(mSensor.name),
mVendor(mSensor.vendor),
mPermission(mSensor.requiredPermission),
mStringType(mSensor.stringType),
mGenerated(false) {
mSensor.name = mName.c_str();
mSensor.vendor = mVendor.c_str();
mSensor.requiredPermission = mPermission.c_str();
mSensor.stringType = mStringType.c_str();
mSensor.handle = handle;
memset(&mEvent, 0, sizeof(mEvent));
mEvent.version = sizeof(mEvent);
sensor->getUuid(mUuid);
ALOGV("Connection report init: name = %s, handle = %d", mSensor.name, mSensor.handle);
}
DynamicSensorManager::ConnectionReport::~ConnectionReport() {
ALOGV("Connection report dtor: name = %s, handle = %d", mSensor.name, mSensor.handle);
}
const sensors_event_t& DynamicSensorManager::ConnectionReport::
generateConnectionEvent(int metaHandle) {
if (!mGenerated) {
mEvent.sensor = metaHandle;
mEvent.type = SENSOR_TYPE_DYNAMIC_SENSOR_META;
mEvent.timestamp = elapsedRealtimeNano();
mEvent.dynamic_sensor_meta =
(dynamic_sensor_meta_event_t) {true, mSensor.handle, &mSensor, {0}};
memcpy(&mEvent.dynamic_sensor_meta.uuid, &mUuid, sizeof(mEvent.dynamic_sensor_meta.uuid));
mGenerated = true;
}
return mEvent;
}
void DynamicSensorManager::ConnectionReport::
fillDisconnectionEvent(sensors_event_t* event, int metaHandle, int handle) {
memset(event, 0, sizeof(sensors_event_t));
event->version = sizeof(sensors_event_t);
event->sensor = metaHandle;
event->type = SENSOR_TYPE_DYNAMIC_SENSOR_META;
event->timestamp = elapsedRealtimeNano();
event->dynamic_sensor_meta.connected = false;
event->dynamic_sensor_meta.handle = handle;
}
} // namespace SensorHalExt
} // namespace android

View file

@ -0,0 +1,137 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
#ifndef ANDROID_SENSORHAL_EXT_DYNAMIC_SENSOR_MANAGER_H
#define ANDROID_SENSORHAL_EXT_DYNAMIC_SENSOR_MANAGER_H
#include "SensorEventCallback.h"
#include "RingBuffer.h"
#include <hardware/sensors.h>
#include <utils/RefBase.h>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
namespace android {
namespace SensorHalExt {
class BaseDynamicSensorDaemon;
class DynamicSensorManager : public SensorEventCallback {
public:
// handleBase is reserved for the dynamic sensor meta sensor.
// handleMax must be greater than handleBase + 1.
// This class has two operation mode depending on callback: 1) extension, 2) stand-alone.
// In extension mode, callback must not be nullptr. Sensor event generated will be submitted to
// buffer of primary sensor HAL implementation. In stand-alone mode, callback must be nullptr.
// Generated sensor events will be added into internal buffer waiting for poll() function to
// pick up.
//
static DynamicSensorManager* createInstance(
int handleBase, int handleCount, SensorEventCallback *callback);
virtual ~DynamicSensorManager();
// calls to add or remove sensor, called from sensor daemon
bool registerSensor(sp<BaseSensorObject> sensor);
void unregisterSensor(sp<BaseSensorObject> sensor);
// Determine if a sensor handle is in the range defined in constructor.
// It does not test if sensor handle is valid.
bool owns(int handle) const;
// handles sensor hal requests.
int activate(int handle, bool enable);
int batch(int handle, nsecs_t sample_period, nsecs_t batch_period);
int setDelay(int handle, nsecs_t sample_period);
int flush(int handle);
int poll(sensors_event_t * data, int count);
// SensorEventCallback
virtual int submitEvent(sp<BaseSensorObject>, const sensors_event_t &e) override;
// get meta sensor struct
const sensor_t& getDynamicMetaSensor() const;
protected:
DynamicSensorManager(int handleBase, int handleMax, SensorEventCallback* callback);
private:
// a helper class used for generate connection and disconnection report
class ConnectionReport {
public:
ConnectionReport() {}
ConnectionReport(int handle, sp<BaseSensorObject> sensor);
~ConnectionReport();
const sensors_event_t& generateConnectionEvent(int metaHandle);
static void fillDisconnectionEvent(sensors_event_t* event, int metaHandle, int handle);
private:
sensor_t mSensor;
std::string mName;
std::string mVendor;
std::string mPermission;
std::string mStringType;
sensors_event_t mEvent;
uint8_t mUuid[16];
bool mGenerated;
DISALLOW_EVIL_CONSTRUCTORS(ConnectionReport);
};
// returns next available handle to use upon a new sensor connection, or -1 if we run out.
int getNextAvailableHandle();
// TF: int foo(sp<BaseSensorObject> obj);
template <typename TF>
int operateSensor(int handle, TF f) const {
std::lock_guard<std::mutex> lk(mLock);
const auto i = mMap.find(handle);
if (i == mMap.end()) {
return BAD_VALUE;
}
sp<BaseSensorObject> s = i->second.promote();
if (s == nullptr) {
// sensor object is already gone
return BAD_VALUE;
}
return f(s);
}
// available sensor handle space
const std::pair<int, int> mHandleRange;
sensor_t mMetaSensor;
// immutable pointer to event callback, used in extention mode.
SensorEventCallback * const mCallback;
// RingBuffer used in standalone mode
static constexpr size_t kFifoSize = 4096; //4K events
mutable std::mutex mFifoLock;
RingBuffer mFifo;
// mapping between handle and SensorObjects
mutable std::mutex mLock;
int mNextHandle;
std::unordered_map<int, wp<BaseSensorObject> > mMap;
std::unordered_map<void *, int> mReverseMap;
mutable std::unordered_map<int, ConnectionReport> mPendingReport;
// daemons
std::vector<sp<BaseDynamicSensorDaemon>> mDaemonVector;
};
} // namespace SensorHalExt
} // namespace android
#endif // ANDROID_SENSORHAL_EXT_DYNAMIC_SENSOR_MANAGER_H

View file

@ -0,0 +1,104 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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 "RingBuffer.h"
#include <stdlib.h>
#include <string.h>
namespace android {
RingBuffer::RingBuffer(size_t size)
: mSize(size),
mData((sensors_event_t *)malloc(sizeof(sensors_event_t) * mSize)),
mReadPos(0),
mWritePos(0) {
}
RingBuffer::~RingBuffer() {
free(mData);
mData = NULL;
}
ssize_t RingBuffer::write(const sensors_event_t *ev, size_t size) {
Mutex::Autolock autoLock(mLock);
size_t numAvailableToRead = mWritePos - mReadPos;
size_t numAvailableToWrite = mSize - numAvailableToRead;
if (size > numAvailableToWrite) {
size = numAvailableToWrite;
}
size_t writePos = (mWritePos % mSize);
size_t copy = mSize - writePos;
if (copy > size) {
copy = size;
}
memcpy(&mData[writePos], ev, copy * sizeof(sensors_event_t));
if (size > copy) {
memcpy(mData, &ev[copy], (size - copy) * sizeof(sensors_event_t));
}
mWritePos += size;
if (numAvailableToRead == 0 && size > 0) {
mNotEmptyCondition.broadcast();
}
return size;
}
ssize_t RingBuffer::read(sensors_event_t *ev, size_t size) {
Mutex::Autolock autoLock(mLock);
size_t numAvailableToRead;
for (;;) {
numAvailableToRead = mWritePos - mReadPos;
if (numAvailableToRead > 0) {
break;
}
mNotEmptyCondition.wait(mLock);
}
if (size > numAvailableToRead) {
size = numAvailableToRead;
}
size_t readPos = (mReadPos % mSize);
size_t copy = mSize - readPos;
if (copy > size) {
copy = size;
}
memcpy(ev, &mData[readPos], copy * sizeof(sensors_event_t));
if (size > copy) {
memcpy(&ev[copy], mData, (size - copy) * sizeof(sensors_event_t));
}
mReadPos += size;
return size;
}
} // namespace android

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
#ifndef RING_BUFFER_H_
#define RING_BUFFER_H_
#include <media/stagefright/foundation/ABase.h>
#include <hardware/sensors.h>
#include <utils/threads.h>
namespace android {
class RingBuffer {
public:
explicit RingBuffer(size_t size);
~RingBuffer();
ssize_t write(const sensors_event_t *ev, size_t size);
ssize_t read(sensors_event_t *ev, size_t size);
private:
Mutex mLock;
Condition mNotEmptyCondition;
size_t mSize;
sensors_event_t *mData;
size_t mReadPos, mWritePos;
DISALLOW_EVIL_CONSTRUCTORS(RingBuffer);
};
} // namespace android
#endif // RING_BUFFER_H_

View file

@ -0,0 +1,40 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
#ifndef ANDROID_SENSORHAL_DSE_SENSOR_EVENT_CALLBACK_H
#define ANDROID_SENSORHAL_DSE_SENSOR_EVENT_CALLBACK_H
#include <hardware/sensors.h>
#include <utils/RefBase.h>
namespace android {
namespace SensorHalExt {
class BaseSensorObject;
// if timestamp in sensors_event_t has this value, it will be filled at dispatcher.
constexpr int64_t TIMESTAMP_AUTO_FILL = -1;
class SensorEventCallback {
public:
virtual int submitEvent(sp<BaseSensorObject> sensor, const sensors_event_t &e) = 0;
virtual ~SensorEventCallback() = default;
};
} // namespace SensorHalExt
} // namespace android
#endif // ANDROID_SENSORHAL_DSE_SENSOR_EVENT_CALLBACK_H

View file

@ -0,0 +1,167 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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 "DynamicSensorManager.h"
#include "sensors.h"
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
#include <utils/Log.h>
#include <errno.h>
#include <string.h>
using namespace android;
////////////////////////////////////////////////////////////////////////////////
SensorContext::SensorContext(const struct hw_module_t *module) {
memset(&device, 0, sizeof(device));
device.common.tag = HARDWARE_DEVICE_TAG;
device.common.version = SENSORS_DEVICE_API_VERSION_1_3;
device.common.module = const_cast<hw_module_t *>(module);
device.common.close = CloseWrapper;
device.activate = ActivateWrapper;
device.setDelay = SetDelayWrapper;
device.poll = PollWrapper;
device.batch = BatchWrapper;
device.flush = FlushWrapper;
// initialize dynamic sensor manager
int32_t base = property_get_int32("sensor.dynamic_sensor_hal.handle_base", kDynamicHandleBase);
int32_t count =
property_get_int32("sensor.dynamic_sensor_hal.handle_count", kMaxDynamicHandleCount);
mDynamicSensorManager.reset(DynamicSensorManager::createInstance(base, count, nullptr));
}
int SensorContext::close() {
delete this;
return 0;
}
int SensorContext::activate(int handle, int enabled) {
return mDynamicSensorManager->activate(handle, enabled);
}
int SensorContext::setDelay(int handle, int64_t delayNs) {
return mDynamicSensorManager->setDelay(handle, delayNs);
}
int SensorContext::poll(sensors_event_t *data, int count) {
return mDynamicSensorManager->poll(data, count);
}
int SensorContext::batch(
int handle,
int64_t sampling_period_ns,
int64_t max_report_latency_ns) {
return mDynamicSensorManager->batch(handle, sampling_period_ns, max_report_latency_ns);
}
int SensorContext::flush(int handle) {
return mDynamicSensorManager->flush(handle);
}
// static
int SensorContext::CloseWrapper(struct hw_device_t *dev) {
return reinterpret_cast<SensorContext *>(dev)->close();
}
// static
int SensorContext::ActivateWrapper(
struct sensors_poll_device_t *dev, int handle, int enabled) {
return reinterpret_cast<SensorContext *>(dev)->activate(handle, enabled);
}
// static
int SensorContext::SetDelayWrapper(
struct sensors_poll_device_t *dev, int handle, int64_t delayNs) {
return reinterpret_cast<SensorContext *>(dev)->setDelay(handle, delayNs);
}
// static
int SensorContext::PollWrapper(
struct sensors_poll_device_t *dev, sensors_event_t *data, int count) {
return reinterpret_cast<SensorContext *>(dev)->poll(data, count);
}
// static
int SensorContext::BatchWrapper(
struct sensors_poll_device_1 *dev,
int handle,
int flags,
int64_t sampling_period_ns,
int64_t max_report_latency_ns) {
(void) flags;
return reinterpret_cast<SensorContext *>(dev)->batch(
handle, sampling_period_ns, max_report_latency_ns);
}
// static
int SensorContext::FlushWrapper(struct sensors_poll_device_1 *dev, int handle) {
return reinterpret_cast<SensorContext *>(dev)->flush(handle);
}
size_t SensorContext::getSensorList(sensor_t const **list) {
*list = &(mDynamicSensorManager->getDynamicMetaSensor());
return 1;
}
////////////////////////////////////////////////////////////////////////////////
static sensor_t const *sensor_list;
static int open_sensors(
const struct hw_module_t *module,
const char *,
struct hw_device_t **dev) {
SensorContext *ctx = new SensorContext(module);
ctx->getSensorList(&sensor_list);
*dev = &ctx->device.common;
return 0;
}
static struct hw_module_methods_t sensors_module_methods = {
.open = open_sensors
};
static int get_sensors_list(
struct sensors_module_t *,
struct sensor_t const **list) {
*list = sensor_list;
return 1;
}
static int set_operation_mode(unsigned int mode) {
return (mode) ? -EINVAL : 0;
}
struct sensors_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = SENSORS_HARDWARE_MODULE_ID,
.name = "Google Dynamic Sensor Manager",
.author = "Google",
.methods = &sensors_module_methods,
.dso = NULL,
.reserved = {0},
},
.get_sensors_list = get_sensors_list,
.set_operation_mode = set_operation_mode,
};

View file

@ -0,0 +1,88 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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.
*/
#ifndef SENSORS_H_
#define SENSORS_H_
#include <hardware/hardware.h>
#include <hardware/sensors.h>
#include <media/stagefright/foundation/ABase.h>
#include <utils/RefBase.h>
#include <memory>
#include <unordered_set>
#include <vector>
namespace android {
namespace SensorHalExt {
class DynamicSensorManager;
} // namespace BaseSensorObject
} // namespace android
using android::SensorHalExt::DynamicSensorManager;
class SensorContext {
public:
struct sensors_poll_device_1 device;
explicit SensorContext(const struct hw_module_t *module);
size_t getSensorList(sensor_t const **list);
private:
int close();
int activate(int handle, int enabled);
int setDelay(int handle, int64_t delayNs);
int poll(sensors_event_t *data, int count);
int batch(int handle, int64_t sampling_period_ns,
int64_t max_report_latency_ns);
int flush(int handle);
// static wrappers
static int CloseWrapper(struct hw_device_t *dev);
static int ActivateWrapper(
struct sensors_poll_device_t *dev, int handle, int enabled);
static int SetDelayWrapper(
struct sensors_poll_device_t *dev, int handle, int64_t delayNs);
static int PollWrapper(
struct sensors_poll_device_t *dev, sensors_event_t *data, int count);
static int BatchWrapper(
struct sensors_poll_device_1 *dev,
int handle,
int flags,
int64_t sampling_period_ns,
int64_t max_report_latency_ns);
static int FlushWrapper(struct sensors_poll_device_1 *dev, int handle);
// default ~16 million handles for dynamic sensor use, can be overriden by system property
static constexpr int32_t kDynamicHandleBase = 0x10000;
static constexpr int32_t kDynamicHandleEnd = 0x1000000;
static constexpr int32_t kMaxDynamicHandleCount = kDynamicHandleEnd - kDynamicHandleBase;
std::unique_ptr<DynamicSensorManager> mDynamicSensorManager;
DISALLOW_EVIL_CONSTRUCTORS(SensorContext);
};
#endif // SENSORS_H_