upload android base code part1

This commit is contained in:
August 2018-08-08 15:50:00 +08:00
parent e02f198e2d
commit 0a1de6c4b3
48159 changed files with 9071466 additions and 0 deletions

View file

@ -0,0 +1,89 @@
// This file is autogenerated by hidl-gen. Do not edit manually.
filegroup {
name: "android.frameworks.sensorservice@1.0_hal",
srcs: [
"types.hal",
"IDirectReportChannel.hal",
"IEventQueue.hal",
"IEventQueueCallback.hal",
"ISensorManager.hal",
],
}
genrule {
name: "android.frameworks.sensorservice@1.0_genc++",
tools: ["hidl-gen"],
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.frameworks:frameworks/hardware/interfaces -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.frameworks.sensorservice@1.0",
srcs: [
":android.frameworks.sensorservice@1.0_hal",
],
out: [
"android/frameworks/sensorservice/1.0/types.cpp",
"android/frameworks/sensorservice/1.0/DirectReportChannelAll.cpp",
"android/frameworks/sensorservice/1.0/EventQueueAll.cpp",
"android/frameworks/sensorservice/1.0/EventQueueCallbackAll.cpp",
"android/frameworks/sensorservice/1.0/SensorManagerAll.cpp",
],
}
genrule {
name: "android.frameworks.sensorservice@1.0_genc++_headers",
tools: ["hidl-gen"],
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.frameworks:frameworks/hardware/interfaces -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.frameworks.sensorservice@1.0",
srcs: [
":android.frameworks.sensorservice@1.0_hal",
],
out: [
"android/frameworks/sensorservice/1.0/types.h",
"android/frameworks/sensorservice/1.0/hwtypes.h",
"android/frameworks/sensorservice/1.0/IDirectReportChannel.h",
"android/frameworks/sensorservice/1.0/IHwDirectReportChannel.h",
"android/frameworks/sensorservice/1.0/BnHwDirectReportChannel.h",
"android/frameworks/sensorservice/1.0/BpHwDirectReportChannel.h",
"android/frameworks/sensorservice/1.0/BsDirectReportChannel.h",
"android/frameworks/sensorservice/1.0/IEventQueue.h",
"android/frameworks/sensorservice/1.0/IHwEventQueue.h",
"android/frameworks/sensorservice/1.0/BnHwEventQueue.h",
"android/frameworks/sensorservice/1.0/BpHwEventQueue.h",
"android/frameworks/sensorservice/1.0/BsEventQueue.h",
"android/frameworks/sensorservice/1.0/IEventQueueCallback.h",
"android/frameworks/sensorservice/1.0/IHwEventQueueCallback.h",
"android/frameworks/sensorservice/1.0/BnHwEventQueueCallback.h",
"android/frameworks/sensorservice/1.0/BpHwEventQueueCallback.h",
"android/frameworks/sensorservice/1.0/BsEventQueueCallback.h",
"android/frameworks/sensorservice/1.0/ISensorManager.h",
"android/frameworks/sensorservice/1.0/IHwSensorManager.h",
"android/frameworks/sensorservice/1.0/BnHwSensorManager.h",
"android/frameworks/sensorservice/1.0/BpHwSensorManager.h",
"android/frameworks/sensorservice/1.0/BsSensorManager.h",
],
}
cc_library {
name: "android.frameworks.sensorservice@1.0",
defaults: ["hidl-module-defaults"],
generated_sources: ["android.frameworks.sensorservice@1.0_genc++"],
generated_headers: ["android.frameworks.sensorservice@1.0_genc++_headers"],
export_generated_headers: ["android.frameworks.sensorservice@1.0_genc++_headers"],
vendor_available: true,
vndk: {
enabled: true,
},
shared_libs: [
"libhidlbase",
"libhidltransport",
"libhwbinder",
"liblog",
"libutils",
"libcutils",
"android.hardware.sensors@1.0",
],
export_shared_lib_headers: [
"libhidlbase",
"libhidltransport",
"libhwbinder",
"libutils",
"android.hardware.sensors@1.0",
],
}

View file

@ -0,0 +1,56 @@
/*
* 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.
*/
package android.frameworks.sensorservice@1.0;
import android.hardware.sensors@1.0::RateLevel;
/**
* The interface represents a direct channel created by
* ISensorManager.createSharedMemoryDirectChannel() and
* ISensorMangaer.createHardwareBufferDirectChannel().
*/
interface IDirectReportChannel {
/**
* Configure direct report on channel
*
* Configure sensor direct report on a direct channel: set rate to value
* other than STOP so that sensor event can be directly written into the
* shared memory region used for creating the channel; set rate to STOP will
* stop the sensor direct report.
*
* To stop all active sensor direct report configured to a channel, set
* sensorHandle to -1 and rate to STOP.
*
* @param sensorHandle handle of the sensor to operate on. If it is -1
* and rate is STOP, the call must stop of all active
* sensor direct report.
* @param rate rate level value to set on the specified sensor.
*
* @return result OK on success;
* BAD_VALUE if parameter is invalid (for example,
* rate level is not supported by sensor, etc);
* INVALID_OPERATION if functionality is not supported.
* @return token the token used to distinguish sensor events from
* multiple different sensors of the same type in a
* single direct channel, or 0 if: (1) no such token
* may be returned or (2) error (in which case result
* must be value other than OK).
*/
configure(int32_t sensorHandle, RateLevel rate)
generates (int32_t token, Result result);
};

View file

@ -0,0 +1,53 @@
/*
* 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.
*/
package android.frameworks.sensorservice@1.0;
/**
* An IEventQueue is an interface to manage an event queue created by
* ISensorManager.
*/
interface IEventQueue {
/**
* Enable the selected sensor with a specified sampling period and
* max batch report latency. If enableSensor is called multiple times on the
* same sensor, the previous calls must be overridden by the last call.
*
* @param sensorHandle the sensor to enable. Must be a sensor acquired from
* the ISensorManager that creates this IEventQueue.
* @param samplingPeriodUs
* sampling period in microseconds.
* @param maxBatchReportLatencyUs
* max batch report latency in microseconds.
* @return result OK if successful, or
* PERMISSION_DENIED, BAD_VALUE, INVALID_OPERATION,
* NO_INIT for errors.
*/
enableSensor(int32_t sensorHandle,
int32_t samplingPeriodUs,
int64_t maxBatchReportLatencyUs)
generates (Result result);
/**
* Disable the selected sensor.
*
* @param sensorHandle the sensor to disable. Must be a sensor acquired from
* the ISensorManager that creates this IEventQueue.
* @return result OK if successful,
* BAD_VALUE or NO_INIT for errors.
*/
disableSensor(int32_t sensorHandle) generates (Result result);
};

View file

@ -0,0 +1,37 @@
/*
* 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.
*/
package android.frameworks.sensorservice@1.0;
import android.hardware.sensors@1.0::Event;
/**
* An IEventQueueCallback describes the callback that is called upon
* any events.
*/
interface IEventQueueCallback {
/**
* When any event is obtained from the sensor, this function must be called
* with the event data.
*
* Implementation of this function must finish in short time predictably.
* It must never block or run for extended period of time. It must offload
* heavy computation to a separate thread.
*
* @param event the event data.
*/
oneway onEvent(Event event);
};

View file

@ -0,0 +1,122 @@
/*
* 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.
*/
package android.frameworks.sensorservice@1.0;
import IDirectReportChannel;
import IEventQueue;
import IEventQueueCallback;
import android.hardware.sensors@1.0::SensorInfo;
import android.hardware.sensors@1.0::SensorType;
/**
* ISensorManager is an interface to manage sensors
*
* This file provides a set of functions that uses
* ISensorManager to access and list hardware sensors.
*/
interface ISensorManager {
/**
* Get the list of available sensors.
*
* @return list the list of available sensors, or empty on failure
* @return result OK on success or UNKNOWN_ERROR on failure
*/
getSensorList() generates (vec<SensorInfo> list, Result result);
/**
* Get the default sensor of the specified type.
*
* @return sensor the default sensor for the given type, or undetermined
* value on failure.
* @return result OK on success or
NOT_EXIST if no sensor of that type exists.
*/
getDefaultSensor(SensorType type)
generates (SensorInfo sensor, Result result);
/**
* Create direct channel based on shared memory
*
* Create a direct channel of DIRECT_CHANNEL_ASHMEM type to be used
* for configuring sensor direct report.
*
* The memory layout looks as follows. These offsets can be found in
* android.hardware.sensors@1.0::SensorsEventFormatOffset.
* offset type name
* -----------------------------------
* 0x0000 int32_t size (SensorsEventFormatOffset::TOTAL_LENGTH)
* 0x0004 int32_t sensor report token
* 0x0008 int32_t type (see android.hardware.sensors@1.0::SensorType)
* 0x000C uint32_t atomic counter
* 0x0010 int64_t timestamp (see android.hardware.sensors@1.0::Event)
* 0x0018 float[16]/ data
* int64_t[8]
* 0x0058 int32_t[4] reserved (set to zero)
*
* @param mem the shared memory to use, must be ashmem.
* @param size the intended size to be used. The following must be true:
* SensorsEventFormatOffset::TOTAL_LENGTH <= size <= mem.size
*
* @return chan The created channel, or NULL if failure.
* @return result OK if successful;
* BAD_VALUE if size > mem.size();
* BAD_VALUE if size < TOTAL_LENGTH;
* NO_MEMORY, NO_INIT, BAD_VALUE for underlying errors;
* UNKNOWN_ERROR if the underlying error is not recognized;
* UNKNOWN_ERROR if the underlying call returns channelId = 0
*/
createAshmemDirectChannel(memory mem, uint64_t size)
generates (IDirectReportChannel chan, Result result);
/**
* Create direct channel based on hardware buffer
*
* Create a direct channel of DIRECT_CHANNEL_GRALLOC type to be used
* for configuring sensor direct report.
*
* @param buffer file descriptor describing the gralloc buffer.
* @param size the intended size to be used, must be less than or equal
* to the size of the buffer.
*
* @return chan The created channel, or NULL if failure.
* @return result OK if successful;
* NO_MEMORY, NO_INIT, BAD_VALUE for underlying errors;
* UNKNOWN_ERROR if the underlying error is not recognized;
* UNKNOWN_ERROR if the underlying call returns channelId = 0
*/
createGrallocDirectChannel(handle buffer, uint64_t size)
generates (IDirectReportChannel chan, Result result);
/**
* Create a sensor event queue.
*
* Create a sensor event queue with an IEventQueueCallback object.
* Subsequently, one can enable sensors on the event queue so that sensor
* events are passed via the specified callback.
*
* @param callback the callback to call on events. Must not be null.
* @return queue the event queue created. null on failure.
* @return result OK if successful, BAD_VALUE if callback is null,
* or other Result values for any underlying errors.
*/
createEventQueue(IEventQueueCallback callback)
generates (IEventQueue queue, Result result);
};

View file

@ -0,0 +1,140 @@
==== Summary ====
android.frameworks.sensorservice@1.0 is a package that mimics the sensors API in
NDK (sensor.h). It includes a subset of these APIs and introduces a few
adaptations.
=== Design Details ===
- ISensorManager
ISensorMangaer includes member functions that adapts the ASensorManager_*
series in NDK. An instance of ISensorManager must be able to
- retrieve sensors
- create direct report channel
- create event queue
- IDirectReportChannel
IDirectReportChannel corresponds to a channel ID, an integer obtained in
ASensorManager_createSharedMemoryDirectChannel and
ASensorManager_createHardwareBufferDirectChannel. An instance of
IDirectReportChannel must also destroy it against the sensor manager. An
IDirectReportChannel must be able to configure itself (an adaptation to
ASensorManager_configureDirectReport). The implementation must also call
ASensorManager_destroyEventQueue on destruction of IDirectReportChannel.
Usage typically looks like this (transaction errors are not handled):
sp<ISensorManager> manager = ISensorManager::getService();
int32_t sensorHandle;
manager->getDefaultSensor(SensorType::GYROSCOPE,
[&sensorHandle] (const auto &info) {
sensorHandle = info.sensorHandle;
});
hidl_memory mem;
const uint64_t size = 4096;
::android::hidl::memory::V1_0::IAllocator::getService()->allocate(size,
[&](auto, const auto &m) { mem = m; });
if (!mem.handle()) {
/* error handling */
}
sp<IDirectChannel> chan;
Result res;
manager->createAshmemDirectChannel(mem, size,
[&chan, &res] (const auto &c, auto r) {
chan = c; res = r;
});
if (res != Result::OK) { /* error handling */ }
chan->configure(sensorHandle, RateLevel::FAST, [&](auto token, auto result) {
if (result != Result::OK) {
/* error handling */
}
});
/* obtain sensor events from shared memory */
chan->configure(sensorHandle, RateLevel::STOP, [&](auto token, auto result) {
if (result != Result::OK) {
/* error handling */
}
});
/*
* Free the channel.
* kernel calls decStrong() on server side implementation of IDirectChannel,
* hence resources are freed as well.
*/
chan = nullptr;
- IEventQueue, IEventQueueCallback
IEventQueue includes member functions that adapts some of the
ASensorEventQueue_* seeries in NDK. An instance of IEventQueue must be able to
- enable selected sensors (adapts ASensorEventQueue_registerSensor)
- disable selected sensors (adapts ASensorEventQueue_disableSensor)
The implementation must free all resources related to this IEventQueue instance
and call ASensorManager_destroyEventQueue on destruction of IEventQueue.
Unlike NDK ASensorEventQueue_hasEvents and ASensorEventQueue_getEvents, which
implies a poll model for sensor events, IEventQueue uses a push model by using
callbacks. When creating an event queue, client must provide an instance of
IEventQueueCallback. The implementation of IEventQueue must either use a global
looper or create a new looper to call on ASensorManager_createEventQueue. The
server implementation must use this looper to constantly poll for events, then
invoke the callback when any event is fired.
IEventQueueCallback.onEvent is designed to be oneway, because the server should
not wait for the client to finish handling the event. The callback
should finish in a predictably short time, and should not block or run for an
extended period of time. The callbacks can be invoked in a very high frequency;
a long running callback means delay in handling of subsequent events and filling
up the (kernel binder buffer) memory space of the client process, eventually the
server sees a transaction error when issuing the callback. It is up to the
client to be configured single-threaded or multi-threaded to handle these
callbacks.
- Single-threaded clients receive events in the correct order in the same
thread.
- Multi-threaded clients receive events in the correct order but in
different threads; it is the clients' responsibility to deal with
concurrency issues and handle events in the expected order to avoid race
conditions.
Usage typically looks like this (transaction errors are not handled):
struct Callback : IEventQueueCallback {
Return<void> onEvent(const Event &e) {
/* handle sensor event e */
}
};
sp<ISensorManager> manager = ISensorManager::getService();
int32_t sensorHandle;
manager->getDefaultSensor(SensorType::GYROSCOPE,
[&sensorHandle] (const auto &info) {
sensorHandle = info.sensorHandle;
});
sp<IEventQueue> queue;
Result res;
manager->createEventQueue(new Callback(),
[&queue, &res] (const auto &q, auto r) {
queue = q; res = r;
});
/* Server side implementation of IEventQueue holds a strong reference to
* the callback. */
if (res != Result::OK) { /* error handling */ }
if (q->enableSensor(sensorHandle,
20000 /* sample period */, 0 /* latency */) != Result::OK) {
/* error handling */
}
/* start receiving events via onEvent */
if (q->disableSensor(sensorHandle) != Result::OK) {
/* error handling */
}
/*
* Free the event queue.
* kernel calls decStrong() on server side implementation of IEventQueue,
* hence resources (including the callback) are freed as well.
*/
queue = nullptr;

View file

@ -0,0 +1,28 @@
/*
* 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.
*/
package android.frameworks.sensorservice@1.0;
enum Result : int32_t {
OK = 0,
NOT_EXIST,
NO_MEMORY,
NO_INIT,
PERMISSION_DENIED,
BAD_VALUE,
INVALID_OPERATION,
UNKNOWN_ERROR
};

View file

@ -0,0 +1,37 @@
//
// Copyright (C) 2016 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.
//
cc_test {
name: "VtsHalSensorManagerV1_0TargetTest",
defaults: ["hidl_defaults"],
srcs: ["VtsHalSensorManagerV1_0TargetTest.cpp"],
shared_libs: [
"libbase",
"libcutils",
"libhidlbase",
"libutils",
"android.hidl.allocator@1.0",
"android.hardware.sensors@1.0",
"android.frameworks.sensorservice@1.0",
],
static_libs: [
"android.hardware.sensors@1.0-convert",
],
cflags: [
"-O0",
"-g",
],
}

View file

@ -0,0 +1,265 @@
/*
* Copyright (C) 2016 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.
*/
#define LOG_TAG "sensor_manager_hidl_hal_test"
#include <android-base/logging.h>
#include <sys/mman.h>
#include <chrono>
#include <thread>
#include <android/sensor.h>
#include <android/frameworks/sensorservice/1.0/ISensorManager.h>
#include <android/frameworks/sensorservice/1.0/types.h>
#include <android/hardware/sensors/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <gtest/gtest.h>
#include <sensors/convert.h>
using ::android::frameworks::sensorservice::V1_0::ISensorManager;
using ::android::frameworks::sensorservice::V1_0::Result;
using ::android::hardware::sensors::V1_0::Event;
using ::android::hardware::sensors::V1_0::RateLevel;
using ::android::hardware::sensors::V1_0::SensorFlagBits;
using ::android::hardware::sensors::V1_0::SensorFlagShift;
using ::android::hardware::sensors::V1_0::SensorType;
using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_memory;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::sp;
template <typename T>
static inline ::testing::AssertionResult isOk(const Return<T> &ret) {
return (ret.isOk()
? ::testing::AssertionSuccess()
: ::testing::AssertionFailure()) << ret.description();
}
template <>
__attribute__((__unused__))
inline ::testing::AssertionResult isOk(const Return<Result> &ret) {
return ((ret.isOk() && ret == Result::OK)
? ::testing::AssertionSuccess()
: ::testing::AssertionFailure())
<< ret.description() << ", "
<< (ret.isOk() ? toString(static_cast<Result>(ret)) : "");
}
static inline ::testing::AssertionResult isOk(Result result) {
using ::android::frameworks::sensorservice::V1_0::toString;
return (result == Result::OK
? ::testing::AssertionSuccess()
: ::testing::AssertionFailure()) << toString(result);
}
template<typename I, typename F>
static ::testing::AssertionResult isIncreasing(I begin, I end, F getField) {
typename std::iterator_traits<I>::pointer lastValue = nullptr;
I iter;
size_t pos;
for (iter = begin, pos = 0; iter != end; ++iter, ++pos) {
if (iter == begin) {
lastValue = &(*iter);
continue;
}
if (getField(*iter) < getField(*lastValue)) {
return ::testing::AssertionFailure() << "Not an increasing sequence, pos = "
<< pos << ", " << getField(*iter) << " < " << getField(*lastValue);
}
}
return ::testing::AssertionSuccess();
}
#define EXPECT_OK(__ret__) EXPECT_TRUE(isOk(__ret__))
#define ASSERT_OK(__ret__) ASSERT_TRUE(isOk(__ret__))
// The main test class for sensorservice HIDL HAL.
class SensorManagerTest : public ::testing::Test {
public:
virtual void SetUp() override {
manager_ = ISensorManager::getService();
ASSERT_NE(manager_, nullptr);
ashmem_ = IAllocator::getService("ashmem");
ASSERT_NE(ashmem_, nullptr);
}
virtual void TearDown() override {}
sp<ISensorManager> manager_;
sp<IAllocator> ashmem_;
};
// A class for test environment setup (kept since this file is a template).
class SensorManagerHidlEnvironment : public ::testing::Environment {
public:
virtual void SetUp() {}
virtual void TearDown() {}
};
using map_region = std::unique_ptr<void, std::function<void(void*)>>;
map_region map(const hidl_memory &mem) {
if (mem.handle() == nullptr || mem.handle()->numFds != 1) {
return nullptr;
}
size_t size = mem.size();
void *buf = mmap(nullptr, size, PROT_READ, MAP_SHARED, mem.handle()->data[0], 0);
return map_region{buf, [size](void *localBuf) {
munmap(localBuf, size);
}};
}
/*
* Ping! make sure the service is alive.
*/
TEST_F(SensorManagerTest, Ping) {
EXPECT_OK(manager_->ping());
}
TEST_F(SensorManagerTest, List) {
ASSERT_OK(manager_->getSensorList([] (__unused const auto &list, auto result) {
using ::android::hardware::sensors::V1_0::toString;
ASSERT_OK(result);
// Do something to the list of sensors.
}));
}
TEST_F(SensorManagerTest, Ashmem) {
auto testOne = [this](uint64_t memSize, uint64_t intendedSize,
ISensorManager::createAshmemDirectChannel_cb callback) {
ASSERT_OK(ashmem_->allocate(memSize, [&](bool success, const auto &mem) {
ASSERT_TRUE(success);
ASSERT_NE(mem.handle(), nullptr);
ASSERT_OK(manager_->createAshmemDirectChannel(mem, intendedSize, callback));
}));
};
testOne(16, 16, [](const auto &chan, Result result) {
EXPECT_EQ(result, Result::BAD_VALUE) << "unexpected result when memory size is too small";
EXPECT_EQ(chan, nullptr);
});
testOne(1024, 1024, [](const auto &chan, Result result) {
EXPECT_OK(result);
EXPECT_NE(chan, nullptr);
});
testOne(1024, 2048, [](const auto &chan, Result result) {
EXPECT_EQ(result, Result::BAD_VALUE) << "unexpected result when intended size is too big";
EXPECT_EQ(chan, nullptr);
});
testOne(1024, 16, [](const auto &chan, Result result) {
EXPECT_EQ(result, Result::BAD_VALUE) << "unexpected result when intended size is too small";
EXPECT_EQ(chan, nullptr);
});
}
static std::vector<Event> parseEvents(uint8_t *buf, size_t memSize) {
using O = SensorsEventFormatOffset;
using ::android::hardware::sensors::V1_0::implementation::convertFromSensorEvent;
size_t offset = 0;
int64_t lastCounter = -1;
std::vector<Event> events;
Event event;
while(offset + (size_t)O::TOTAL_LENGTH <= memSize) {
uint8_t *start = buf + offset;
int64_t atomicCounter = *reinterpret_cast<uint32_t *>(start + (size_t)O::ATOMIC_COUNTER);
if (atomicCounter <= lastCounter) {
break;
}
int32_t size = *reinterpret_cast<int32_t *>(start + (size_t)O::SIZE_FIELD);
if (size != (size_t)O::TOTAL_LENGTH) {
// unknown error, events parsed may be wrong, remove all
events.clear();
break;
}
convertFromSensorEvent(*reinterpret_cast<const sensors_event_t *>(start), &event);
events.push_back(event);
lastCounter = atomicCounter;
offset += (size_t)O::TOTAL_LENGTH;
}
return events;
}
TEST_F(SensorManagerTest, Accelerometer) {
using std::literals::chrono_literals::operator""ms;
using ::android::hardware::sensors::V1_0::implementation::convertFromRateLevel;
Result getSensorResult;
int32_t handle;
ASSERT_OK(manager_->getDefaultSensor(SensorType::ACCELEROMETER, [&] (const auto &info, auto result) {
getSensorResult = result;
handle = info.sensorHandle;
if (result == Result::OK) {
ASSERT_TRUE(info.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM);
int maxLevel = (info.flags & SensorFlagBits::MASK_DIRECT_REPORT)
>> (int)SensorFlagShift::DIRECT_REPORT;
ASSERT_TRUE(maxLevel >= convertFromRateLevel(RateLevel::FAST))
<< "Accelerometer does not support fast report rate, test cannot proceed.";
}
}));
if (getSensorResult == Result::NOT_EXIST) {
LOG(WARNING) << "Cannot find accelerometer, skipped SensorManagerTest.Accelerometer";
return;
}
ASSERT_OK(getSensorResult);
const size_t memSize = (size_t)SensorsEventFormatOffset::TOTAL_LENGTH * 300;
ASSERT_OK(ashmem_->allocate(memSize, [&] (bool success, const auto &mem) {
ASSERT_TRUE(success);
map_region buf = map(mem);
ASSERT_NE(buf, nullptr);
ASSERT_OK(manager_->createAshmemDirectChannel(mem, memSize, [&](const auto &chan, Result result) {
ASSERT_OK(result);
ASSERT_NE(chan, nullptr);
int32_t returnedToken;
ASSERT_OK(chan->configure(handle, RateLevel::FAST, [&](auto token, auto res) {
ASSERT_OK(res);
ASSERT_GT(token, 0);
returnedToken = token;
})); // ~200Hz
std::this_thread::sleep_for(500ms);
ASSERT_OK(chan->configure(handle, RateLevel::STOP, [](auto token, auto res) {
ASSERT_OK(res);
ASSERT_EQ(token, 0);
}));
auto events = parseEvents(static_cast<uint8_t *>(buf.get()), memSize);
EXPECT_TRUE(isIncreasing(events.begin(), events.end(), [](const auto &event) {
return event.timestamp;
})) << "timestamp is not monotonically increasing";
for (const auto &event : events) {
EXPECT_EQ(returnedToken, event.sensorHandle)
<< "configure token and sensor handle don't match.";
}
}));
}));
}
int main(int argc, char** argv) {
::testing::AddGlobalTestEnvironment(new SensorManagerHidlEnvironment);
::testing::InitGoogleTest(&argc, argv);
int status = RUN_ALL_TESTS();
LOG(INFO) << "Test result = " << status;
return status;
}

View file

@ -0,0 +1,94 @@
/*
* 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 "ALooper.h"
#include "ASensorEventQueue.h"
#define LOG_TAG "libsensorndkbridge"
#include <android/looper.h>
#include <android-base/logging.h>
using android::Mutex;
ALooper::ALooper()
: mAwoken(false) {
}
void ALooper::signalSensorEvents(ASensorEventQueue *queue) {
Mutex::Autolock autoLock(mLock);
mReadyQueues.insert(queue);
mCondition.signal();
}
void ALooper::wake() {
Mutex::Autolock autoLock(mLock);
mAwoken = true;
mCondition.signal();
}
int ALooper::pollOnce(
int timeoutMillis, int *outFd, int *outEvents, void **outData) {
if (outFd) { *outFd = 0; }
if (outEvents) { *outEvents = 0; }
if (outData) { *outData = NULL; }
int64_t waitUntilNs;
if (timeoutMillis < 0) {
waitUntilNs = -1;
} else {
waitUntilNs =
systemTime(SYSTEM_TIME_MONOTONIC) + timeoutMillis * 1000000ll;
}
Mutex::Autolock autoLock(mLock);
int64_t nowNs;
while ((timeoutMillis < 0
|| (nowNs = systemTime(SYSTEM_TIME_MONOTONIC)) < waitUntilNs)
&& mReadyQueues.empty()
&& !mAwoken) {
if (timeoutMillis < 0) {
mCondition.wait(mLock);
} else {
mCondition.waitRelative(mLock, waitUntilNs - nowNs);
}
}
int result = ALOOPER_POLL_TIMEOUT;
if (!mReadyQueues.empty()) {
result = ALOOPER_POLL_CALLBACK;
for (auto queue : mReadyQueues) {
queue->dispatchCallback();
}
mReadyQueues.clear();
} else if (mAwoken) {
result = ALOOPER_POLL_WAKE;
mAwoken = false;
}
LOG(VERBOSE) << "pollOnce returning " << result;
return result;
}
void ALooper::invalidateSensorQueue(ASensorEventQueue *queue) {
Mutex::Autolock autoLock(mLock);
mReadyQueues.erase(queue);
}

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 A_LOOPER_H_
#define A_LOOPER_H_
#include <android-base/macros.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <set>
struct ASensorEventQueue;
struct ALooper {
ALooper();
void signalSensorEvents(ASensorEventQueue *queue);
void wake();
int pollOnce(int timeoutMillis, int *outFd, int *outEvents, void **outData);
void invalidateSensorQueue(ASensorEventQueue *queue);
private:
android::Mutex mLock;
android::Condition mCondition;
std::set<ASensorEventQueue *> mReadyQueues;
bool mAwoken;
DISALLOW_COPY_AND_ASSIGN(ALooper);
};
#endif // A_LOOPER_H_

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.
*/
#include "ASensorEventQueue.h"
#include "ALooper.h"
#define LOG_TAG "libsensorndkbridge"
#include <android-base/logging.h>
using android::sp;
using android::frameworks::sensorservice::V1_0::Result;
using android::hardware::sensors::V1_0::SensorInfo;
using android::OK;
using android::BAD_VALUE;
using android::Mutex;
using android::hardware::Return;
ASensorEventQueue::ASensorEventQueue(
ALooper *looper, int ident, ALooper_callbackFunc callback, void *data)
: mLooper(looper),
mIdent(ident),
mCallback(callback),
mData(data) {
}
void ASensorEventQueue::setImpl(const sp<IEventQueue> &queueImpl) {
mQueueImpl = queueImpl;
}
int ASensorEventQueue::registerSensor(
ASensorRef sensor,
int32_t samplingPeriodUs,
int64_t maxBatchReportLatencyUs) {
Return<Result> ret = mQueueImpl->enableSensor(
reinterpret_cast<const SensorInfo *>(sensor)->sensorHandle,
samplingPeriodUs,
maxBatchReportLatencyUs);
if (!ret.isOk()) {
return BAD_VALUE;
}
return OK;
}
int ASensorEventQueue::enableSensor(ASensorRef sensor) {
static constexpr int32_t SENSOR_DELAY_NORMAL = 200000;
return registerSensor(
sensor, SENSOR_DELAY_NORMAL, 0 /* maxBatchReportLatencyUs */);
}
int ASensorEventQueue::setEventRate(
ASensorRef sensor, int32_t samplingPeriodUs) {
// Technically this is not supposed to enable the sensor but using this
// API without enabling the sensor first is a no-op, so...
return registerSensor(
sensor, samplingPeriodUs, 0 /* maxBatchReportLatencyUs */);
}
int ASensorEventQueue::disableSensor(ASensorRef sensor) {
Return<Result> ret = mQueueImpl->disableSensor(
reinterpret_cast<const SensorInfo *>(sensor)->sensorHandle);
return ret.isOk() ? OK : BAD_VALUE;
}
ssize_t ASensorEventQueue::getEvents(ASensorEvent *events, size_t count) {
// XXX Should this block if there aren't any events in the queue?
Mutex::Autolock autoLock(mLock);
static_assert(
sizeof(ASensorEvent) == sizeof(sensors_event_t), "mismatched size");
size_t copy = std::min(count, mQueue.size());
for (size_t i = 0; i < copy; ++i) {
reinterpret_cast<sensors_event_t *>(events)[i] = mQueue[i];
}
mQueue.erase(mQueue.begin(), mQueue.begin() + copy);
LOG(VERBOSE) << "ASensorEventQueue::getEvents() returned " << copy << " events.";
return copy;
}
int ASensorEventQueue::hasEvents() const {
return mQueue.empty();
}
Return<void> ASensorEventQueue::onEvent(const Event &event) {
LOG(VERBOSE) << "ASensorEventQueue::onEvent";
{
Mutex::Autolock autoLock(mLock);
mQueue.emplace_back();
sensors_event_t *sensorEvent = &mQueue[mQueue.size() - 1];
android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
event, sensorEvent);
}
mLooper->signalSensorEvents(this);
return android::hardware::Void();
}
void ASensorEventQueue::dispatchCallback() {
if (mCallback != NULL) {
int res = (*mCallback)(-1 /* fd */, ALOOPER_EVENT_INPUT, mData);
if (res == 0) {
mCallback = NULL;
mData = NULL;
}
}
}
void ASensorEventQueue::invalidate() {
mLooper->invalidateSensorQueue(this);
setImpl(nullptr);
}

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.
*/
#ifndef A_SENSOR_EVENT_QUEUE_H_
#define A_SENSOR_EVENT_QUEUE_H_
#include <android/frameworks/sensorservice/1.0/IEventQueue.h>
#include <android/frameworks/sensorservice/1.0/IEventQueueCallback.h>
#include <android/looper.h>
#include <android/sensor.h>
#include <android-base/macros.h>
#include <sensors/convert.h>
#include <utils/Mutex.h>
struct ALooper;
struct ASensorEventQueue
: public android::frameworks::sensorservice::V1_0::IEventQueueCallback {
using Event = android::hardware::sensors::V1_0::Event;
using IEventQueue = android::frameworks::sensorservice::V1_0::IEventQueue;
ASensorEventQueue(
ALooper *looper,
int ident,
ALooper_callbackFunc callback,
void *data);
android::hardware::Return<void> onEvent(const Event &event) override;
void setImpl(const android::sp<IEventQueue> &queueImpl);
int registerSensor(
ASensorRef sensor,
int32_t samplingPeriodUs,
int64_t maxBatchReportLatencyUs);
int enableSensor(ASensorRef sensor);
int disableSensor(ASensorRef sensor);
int setEventRate(ASensorRef sensor, int32_t samplingPeriodUs);
ssize_t getEvents(ASensorEvent *events, size_t count);
int hasEvents() const;
void dispatchCallback();
void invalidate();
private:
ALooper *mLooper;
int mIdent;
ALooper_callbackFunc mCallback;
void *mData;
android::sp<IEventQueue> mQueueImpl;
android::Mutex mLock;
std::vector<sensors_event_t> mQueue;
DISALLOW_COPY_AND_ASSIGN(ASensorEventQueue);
};
#endif // A_SENSOR_EVENT_QUEUE_H_

View file

@ -0,0 +1,447 @@
/*
* 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 "ALooper.h"
#include "ASensorEventQueue.h"
#include "ASensorManager.h"
#define LOG_TAG "libsensorndkbridge"
#include <android-base/logging.h>
#include <android/looper.h>
#include <hidl/HidlTransportSupport.h>
#include <sensors/convert.h>
using android::hardware::sensors::V1_0::SensorInfo;
using android::frameworks::sensorservice::V1_0::IEventQueue;
using android::frameworks::sensorservice::V1_0::ISensorManager;
using android::frameworks::sensorservice::V1_0::Result;
using android::hardware::sensors::V1_0::SensorType;
using android::sp;
using android::wp;
using android::Mutex;
using android::status_t;
using android::OK;
using android::NO_INIT;
using android::BAD_VALUE;
using android::hardware::hidl_vec;
using android::hardware::Return;
static Mutex gLock;
// static
ASensorManager *ASensorManager::sInstance = NULL;
// static
ASensorManager *ASensorManager::getInstance() {
Mutex::Autolock autoLock(gLock);
if (sInstance == NULL) {
sInstance = new ASensorManager;
if (sInstance->initCheck() != OK) {
delete sInstance;
sInstance = NULL;
}
}
return sInstance;
}
void ASensorManager::SensorDeathRecipient::serviceDied(
uint64_t, const wp<::android::hidl::base::V1_0::IBase>&) {
LOG(ERROR) << "Sensor service died. Cleanup sensor manager instance!";
Mutex::Autolock autoLock(gLock);
delete sInstance;
sInstance = NULL;
}
ASensorManager::ASensorManager()
: mInitCheck(NO_INIT) {
mManager = ISensorManager::getService();
if (mManager != NULL) {
mDeathRecipient = new SensorDeathRecipient();
Return<bool> linked = mManager->linkToDeath(mDeathRecipient, /*cookie*/ 0);
if (!linked.isOk()) {
LOG(ERROR) << "Transaction error in linking to sensor service death: " <<
linked.description().c_str();
} else if (!linked) {
LOG(WARNING) << "Unable to link to sensor service death notifications";
} else {
LOG(DEBUG) << "Link to sensor service death notification successful";
mInitCheck = OK;
}
}
}
status_t ASensorManager::initCheck() const {
return mInitCheck;
}
int ASensorManager::getSensorList(ASensorList *out) {
LOG(VERBOSE) << "ASensorManager::getSensorList";
Mutex::Autolock autoLock(mLock);
if (mSensorList == NULL) {
Return<void> ret =
mManager->getSensorList([&](const auto &list, auto result) {
if (result != Result::OK) {
return;
}
mSensors = list;
});
(void)ret.isOk();
mSensorList.reset(new ASensorRef[mSensors.size()]);
for (size_t i = 0; i < mSensors.size(); ++i) {
mSensorList.get()[i] =
reinterpret_cast<ASensorRef>(&mSensors[i]);
}
}
if (out) {
*out = reinterpret_cast<ASensorList>(mSensorList.get());
}
return mSensors.size();
}
ASensorRef ASensorManager::getDefaultSensor(int type) {
(void)getSensorList(NULL /* list */);
ASensorRef defaultSensor = NULL;
Return<void> ret = mManager->getDefaultSensor(
static_cast<SensorType>(type),
[&](const auto &sensor, auto result) {
if (result != Result::OK) {
return;
}
for (size_t i = 0; i < mSensors.size(); ++i) {
if (sensor == mSensors[i]) {
defaultSensor =
reinterpret_cast<ASensorRef>(&mSensors[i]);
break;
}
}
});
(void)ret.isOk();
return defaultSensor;
}
ASensorRef ASensorManager::getDefaultSensorEx(
int /* type */, bool /* wakeup */) {
// XXX ISensorManager's getDefaultSensorEx() lacks a "wakeup" parameter.
return NULL;
}
ASensorEventQueue *ASensorManager::createEventQueue(
ALooper *looper, int ident, ALooper_callbackFunc callback, void *data) {
LOG(VERBOSE) << "ASensorManager::createEventQueue";
sp<ASensorEventQueue> queue =
new ASensorEventQueue(looper, ident, callback, data);
::android::hardware::setMinSchedulerPolicy(queue, SCHED_FIFO, 98);
Result result;
Return<void> ret =
mManager->createEventQueue(
queue, [&](const sp<IEventQueue> &queueImpl, auto tmpResult) {
result = tmpResult;
if (result != Result::OK) {
return;
}
queue->setImpl(queueImpl);
});
if (!ret.isOk() || result != Result::OK) {
LOG(ERROR) << "FAILED to create event queue";
return NULL;
}
queue->incStrong(NULL /* id */);
LOG(VERBOSE) << "Returning event queue " << queue.get();
return queue.get();
}
void ASensorManager::destroyEventQueue(ASensorEventQueue *queue) {
LOG(VERBOSE) << "ASensorManager::destroyEventQueue(" << queue << ")";
queue->invalidate();
queue->decStrong(NULL /* id */);
queue = NULL;
}
////////////////////////////////////////////////////////////////////////////////
ASensorManager *ASensorManager_getInstance() {
return ASensorManager::getInstance();
}
ASensorManager *ASensorManager_getInstanceForPackage(
const char* /* packageName */) {
return ASensorManager::getInstance();
}
#define RETURN_IF_MANAGER_IS_NULL(x) \
do { \
if (manager == NULL) { \
return x; \
} \
} while (0)
#define RETURN_IF_QUEUE_IS_NULL(x) \
do { \
if (queue == NULL) { \
return x; \
} \
} while (0)
#define RETURN_IF_SENSOR_IS_NULL(x) \
do { \
if (sensor == NULL) { \
return x; \
} \
} while (0)
int ASensorManager_getSensorList(ASensorManager* manager, ASensorList* list) {
RETURN_IF_MANAGER_IS_NULL(BAD_VALUE);
return manager->getSensorList(list);
}
ASensor const* ASensorManager_getDefaultSensor(
ASensorManager* manager, int type) {
RETURN_IF_MANAGER_IS_NULL(NULL);
return manager->getDefaultSensor(type);
}
#if 0
ASensor const* ASensorManager_getDefaultSensorEx(
ASensorManager* manager, int type, bool wakeUp) {
RETURN_IF_MANAGER_IS_NULL(NULL);
return manager->getDefaultSensorEx(type, wakeUp);
}
#endif
ASensorEventQueue* ASensorManager_createEventQueue(
ASensorManager* manager,
ALooper* looper,
int ident,
ALooper_callbackFunc callback,
void* data) {
RETURN_IF_MANAGER_IS_NULL(NULL);
if (looper == NULL) {
return NULL;
}
return manager->createEventQueue(looper, ident, callback, data);
}
int ASensorManager_destroyEventQueue(
ASensorManager* manager, ASensorEventQueue* queue) {
RETURN_IF_MANAGER_IS_NULL(BAD_VALUE);
RETURN_IF_QUEUE_IS_NULL(BAD_VALUE);
manager->destroyEventQueue(queue);
queue = NULL;
return OK;
}
#if 0
int ASensorManager_createSharedMemoryDirectChannel(
ASensorManager* manager, int fd, size_t size) {
RETURN_IF_MANAGER_IS_NULL(BAD_VALUE);
return OK;
}
int ASensorManager_createHardwareBufferDirectChannel(
ASensorManager* manager, AHardwareBuffer const * buffer, size_t size) {
RETURN_IF_MANAGER_IS_NULL(BAD_VALUE);
return OK;
}
void ASensorManager_destroyDirectChannel(
ASensorManager* manager, int channelId) {
}
int ASensorManager_configureDirectReport(
ASensorManager* manager,
ASensor const* sensor,
int channelId,int rate) {
RETURN_IF_MANAGER_IS_NULL(BAD_VALUE);
return OK;
}
#endif
int ASensorEventQueue_registerSensor(
ASensorEventQueue* queue,
ASensor const* sensor,
int32_t samplingPeriodUs,
int64_t maxBatchReportLatencyUs) {
LOG(VERBOSE) << "ASensorEventQueue_registerSensor";
RETURN_IF_QUEUE_IS_NULL(BAD_VALUE);
return queue->registerSensor(
sensor, samplingPeriodUs, maxBatchReportLatencyUs);
}
int ASensorEventQueue_enableSensor(
ASensorEventQueue* queue, ASensor const* sensor) {
LOG(VERBOSE) << "ASensorEventQueue_enableSensor(queue " << queue << ")";
RETURN_IF_QUEUE_IS_NULL(BAD_VALUE);
return queue->enableSensor(sensor);
}
int ASensorEventQueue_disableSensor(
ASensorEventQueue* queue, ASensor const* sensor) {
LOG(VERBOSE) << "ASensorEventQueue_disableSensor";
RETURN_IF_QUEUE_IS_NULL(BAD_VALUE);
return queue->disableSensor(sensor);
}
int ASensorEventQueue_setEventRate(
ASensorEventQueue* queue,
ASensor const* sensor,
int32_t usec) {
RETURN_IF_QUEUE_IS_NULL(BAD_VALUE);
return queue->setEventRate(sensor, usec);
}
int ASensorEventQueue_hasEvents(ASensorEventQueue* queue) {
RETURN_IF_QUEUE_IS_NULL(BAD_VALUE);
return queue->hasEvents();
}
ssize_t ASensorEventQueue_getEvents(
ASensorEventQueue* queue, ASensorEvent* events, size_t count) {
LOG(VERBOSE) << "ASensorEventQueue_getEvents";
RETURN_IF_QUEUE_IS_NULL(BAD_VALUE);
return queue->getEvents(events, count);
}
const char *ASensor_getName(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(NULL);
return reinterpret_cast<const SensorInfo *>(sensor)->name.c_str();
}
const char *ASensor_getVendor(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(NULL);
return reinterpret_cast<const SensorInfo *>(sensor)->vendor.c_str();
}
int ASensor_getType(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(ASENSOR_TYPE_INVALID);
return static_cast<int>(
reinterpret_cast<const SensorInfo *>(sensor)->type);
}
float ASensor_getResolution(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(ASENSOR_RESOLUTION_INVALID);
return reinterpret_cast<const SensorInfo *>(sensor)->resolution;
}
int ASensor_getMinDelay(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(ASENSOR_DELAY_INVALID);
return reinterpret_cast<const SensorInfo *>(sensor)->minDelay;
}
int ASensor_getFifoMaxEventCount(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(ASENSOR_FIFO_COUNT_INVALID);
return reinterpret_cast<const SensorInfo *>(sensor)->fifoMaxEventCount;
}
int ASensor_getFifoReservedEventCount(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(ASENSOR_FIFO_COUNT_INVALID);
return reinterpret_cast<const SensorInfo *>(sensor)->fifoReservedEventCount;
}
const char* ASensor_getStringType(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(NULL);
return reinterpret_cast<const SensorInfo *>(sensor)->typeAsString.c_str();
}
extern "C" float ASensor_getMaxRange(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(nanf(""));
return reinterpret_cast<const SensorInfo *>(sensor)->maxRange;
}
#if 0
int ASensor_getReportingMode(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(AREPORTING_MODE_INVALID);
return 0;
}
bool ASensor_isWakeUpSensor(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(false);
return false;
}
bool ASensor_isDirectChannelTypeSupported(
ASensor const* sensor, int channelType) {
RETURN_IF_SENSOR_IS_NULL(false);
return false;
}
int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) {
RETURN_IF_SENSOR_IS_NULL(ASENSOR_DIRECT_RATE_STOP);
return 0;
}
#endif
static ALooper *getTheLooper() {
static ALooper *sLooper = NULL;
Mutex::Autolock autoLock(gLock);
if (sLooper == NULL) {
sLooper = new ALooper;
}
return sLooper;
}
ALooper *ALooper_forThread() {
LOG(VERBOSE) << "ALooper_forThread";
return getTheLooper();
}
ALooper *ALooper_prepare(int /* opts */) {
LOG(VERBOSE) << "ALooper_prepare";
return getTheLooper();
}
int ALooper_pollOnce(
int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int res = getTheLooper()->pollOnce(timeoutMillis, outFd, outEvents, outData);
LOG(VERBOSE) << "ALooper_pollOnce => " << res;
return res;
}
void ALooper_wake(ALooper* looper) {
LOG(VERBOSE) << "ALooper_wake";
looper->wake();
}

View file

@ -0,0 +1,73 @@
/*
* 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 A_SENSOR_MANAGER_H_
#define A_SENSOR_MANAGER_H_
#include <android/frameworks/sensorservice/1.0/ISensorManager.h>
#include <android/sensor.h>
#include <utils/Mutex.h>
#include <utils/RefBase.h>
struct ALooper;
struct ASensorManager {
static ASensorManager *getInstance();
ASensorManager();
android::status_t initCheck() const;
// Returns error or number of sensors returned.
int getSensorList(ASensorList *list);
ASensorRef getDefaultSensor(int type);
ASensorRef getDefaultSensorEx(int type, bool wakeup);
ASensorEventQueue *createEventQueue(
ALooper *looper,
int ident,
ALooper_callbackFunc callback,
void *data);
void destroyEventQueue(ASensorEventQueue *queue);
private:
struct SensorDeathRecipient : public android::hardware::hidl_death_recipient
{
// hidl_death_recipient interface
virtual void serviceDied(uint64_t cookie,
const ::android::wp<::android::hidl::base::V1_0::IBase>& who) override;
};
using ISensorManager = android::frameworks::sensorservice::V1_0::ISensorManager;
using SensorInfo = android::hardware::sensors::V1_0::SensorInfo;
static ASensorManager *sInstance;
android::sp<SensorDeathRecipient> mDeathRecipient = nullptr;
android::status_t mInitCheck;
android::sp<ISensorManager> mManager;
mutable android::Mutex mLock;
android::hardware::hidl_vec<SensorInfo> mSensors;
std::unique_ptr<ASensorRef[]> mSensorList;
DISALLOW_COPY_AND_ASSIGN(ASensorManager);
};
#endif // A_SENSOR_MANAGER_H_

View file

@ -0,0 +1,42 @@
// 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.
cc_library_shared {
name: "libsensorndkbridge",
proprietary: true,
srcs: [
"ALooper.cpp",
"ASensorEventQueue.cpp",
"ASensorManager.cpp",
],
shared_libs: [
"libbase",
"libhidlbase",
"libhidltransport",
"libutils",
"android.frameworks.sensorservice@1.0",
"android.hardware.sensors@1.0",
],
static_libs: [
"android.hardware.sensors@1.0-convert",
],
header_libs: [
"libandroid_sensor_headers",
],
export_header_lib_headers: [
"libandroid_sensor_headers",
],
}