278 lines
10 KiB
C++
278 lines
10 KiB
C++
|
/*
|
||
|
* 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.
|
||
|
*/
|
||
|
|
||
|
#include "SensorList.h"
|
||
|
|
||
|
#include <android/util/ProtoOutputStream.h>
|
||
|
#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
|
||
|
#include <hardware/sensors.h>
|
||
|
#include <utils/String8.h>
|
||
|
|
||
|
#include <cinttypes>
|
||
|
|
||
|
namespace android {
|
||
|
namespace SensorServiceUtil {
|
||
|
|
||
|
const Sensor SensorList::mNonSensor = Sensor("unknown");
|
||
|
|
||
|
bool SensorList::add(
|
||
|
int handle, SensorInterface* si, bool isForDebug, bool isVirtual) {
|
||
|
std::lock_guard<std::mutex> lk(mLock);
|
||
|
if (handle == si->getSensor().getHandle() &&
|
||
|
mUsedHandle.insert(handle).second) {
|
||
|
// will succeed as the mUsedHandle does not have this handle
|
||
|
mHandleMap.emplace(handle, Entry(si, isForDebug, isVirtual));
|
||
|
return true;
|
||
|
}
|
||
|
// handle exist already or handle mismatch
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool SensorList::remove(int handle) {
|
||
|
std::lock_guard<std::mutex> lk(mLock);
|
||
|
auto entry = mHandleMap.find(handle);
|
||
|
if (entry != mHandleMap.end()) {
|
||
|
mHandleMap.erase(entry);
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
String8 SensorList::getName(int handle) const {
|
||
|
return getOne<String8>(
|
||
|
handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getName();},
|
||
|
mNonSensor.getName());
|
||
|
}
|
||
|
|
||
|
String8 SensorList::getStringType(int handle) const {
|
||
|
return getOne<String8>(
|
||
|
handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getStringType();},
|
||
|
mNonSensor.getStringType());
|
||
|
}
|
||
|
|
||
|
sp<SensorInterface> SensorList::getInterface(int handle) const {
|
||
|
return getOne<sp<SensorInterface>>(
|
||
|
handle, [] (const Entry& e) -> sp<SensorInterface> {return e.si;}, nullptr);
|
||
|
}
|
||
|
|
||
|
|
||
|
bool SensorList::isNewHandle(int handle) const {
|
||
|
std::lock_guard<std::mutex> lk(mLock);
|
||
|
return mUsedHandle.find(handle) == mUsedHandle.end();
|
||
|
}
|
||
|
|
||
|
const Vector<Sensor> SensorList::getUserSensors() const {
|
||
|
// lock in forEachEntry
|
||
|
Vector<Sensor> sensors;
|
||
|
forEachEntry(
|
||
|
[&sensors] (const Entry& e) -> bool {
|
||
|
if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()) {
|
||
|
sensors.add(e.si->getSensor());
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
return sensors;
|
||
|
}
|
||
|
|
||
|
const Vector<Sensor> SensorList::getUserDebugSensors() const {
|
||
|
// lock in forEachEntry
|
||
|
Vector<Sensor> sensors;
|
||
|
forEachEntry(
|
||
|
[&sensors] (const Entry& e) -> bool {
|
||
|
if (!e.si->getSensor().isDynamicSensor()) {
|
||
|
sensors.add(e.si->getSensor());
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
return sensors;
|
||
|
}
|
||
|
|
||
|
const Vector<Sensor> SensorList::getDynamicSensors() const {
|
||
|
// lock in forEachEntry
|
||
|
Vector<Sensor> sensors;
|
||
|
forEachEntry(
|
||
|
[&sensors] (const Entry& e) -> bool {
|
||
|
if (!e.isForDebug && e.si->getSensor().isDynamicSensor()) {
|
||
|
sensors.add(e.si->getSensor());
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
return sensors;
|
||
|
}
|
||
|
|
||
|
const Vector<Sensor> SensorList::getVirtualSensors() const {
|
||
|
// lock in forEachEntry
|
||
|
Vector<Sensor> sensors;
|
||
|
forEachEntry(
|
||
|
[&sensors] (const Entry& e) -> bool {
|
||
|
if (e.isVirtual) {
|
||
|
sensors.add(e.si->getSensor());
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
return sensors;
|
||
|
}
|
||
|
|
||
|
std::string SensorList::dump() const {
|
||
|
String8 result;
|
||
|
|
||
|
forEachSensor([&result] (const Sensor& s) -> bool {
|
||
|
result.appendFormat(
|
||
|
"%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
|
||
|
") | perm: %s | flags: 0x%08x\n",
|
||
|
s.getHandle(),
|
||
|
s.getName().string(),
|
||
|
s.getVendor().string(),
|
||
|
s.getVersion(),
|
||
|
s.getStringType().string(),
|
||
|
s.getType(),
|
||
|
s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a",
|
||
|
static_cast<int>(s.getFlags()));
|
||
|
|
||
|
result.append("\t");
|
||
|
const int reportingMode = s.getReportingMode();
|
||
|
if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
|
||
|
result.append("continuous | ");
|
||
|
} else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
|
||
|
result.append("on-change | ");
|
||
|
} else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
|
||
|
result.append("one-shot | ");
|
||
|
} else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
|
||
|
result.append("special-trigger | ");
|
||
|
} else {
|
||
|
result.append("unknown-mode | ");
|
||
|
}
|
||
|
|
||
|
if (s.getMaxDelay() > 0) {
|
||
|
result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
|
||
|
} else {
|
||
|
result.appendFormat("maxDelay=%" PRId32 "us | ", s.getMaxDelay());
|
||
|
}
|
||
|
|
||
|
if (s.getMinDelay() > 0) {
|
||
|
result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
|
||
|
} else {
|
||
|
result.appendFormat("minDelay=%" PRId32 "us | ", s.getMinDelay());
|
||
|
}
|
||
|
|
||
|
if (s.getFifoMaxEventCount() > 0) {
|
||
|
result.appendFormat("FIFO (max,reserved) = (%" PRIu32 ", %" PRIu32 ") events | ",
|
||
|
s.getFifoMaxEventCount(),
|
||
|
s.getFifoReservedEventCount());
|
||
|
} else {
|
||
|
result.append("no batching | ");
|
||
|
}
|
||
|
|
||
|
if (s.isWakeUpSensor()) {
|
||
|
result.appendFormat("wakeUp | ");
|
||
|
} else {
|
||
|
result.appendFormat("non-wakeUp | ");
|
||
|
}
|
||
|
|
||
|
if (s.isDataInjectionSupported()) {
|
||
|
result.appendFormat("data-injection, ");
|
||
|
}
|
||
|
|
||
|
if (s.isDynamicSensor()) {
|
||
|
result.appendFormat("dynamic, ");
|
||
|
}
|
||
|
|
||
|
if (s.hasAdditionalInfo()) {
|
||
|
result.appendFormat("has-additional-info, ");
|
||
|
}
|
||
|
result.append("\n");
|
||
|
|
||
|
if (s.getHighestDirectReportRateLevel() > SENSOR_DIRECT_RATE_STOP) {
|
||
|
result.appendFormat("\thighest rate level = %d, support shared mem: ",
|
||
|
s.getHighestDirectReportRateLevel());
|
||
|
if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM)) {
|
||
|
result.append("ashmem, ");
|
||
|
}
|
||
|
if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)) {
|
||
|
result.append("gralloc, ");
|
||
|
}
|
||
|
result.append("\n");
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
return std::string(result.string());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Dump debugging information as android.service.SensorListProto protobuf message using
|
||
|
* ProtoOutputStream.
|
||
|
*
|
||
|
* See proto definition and some notes about ProtoOutputStream in
|
||
|
* frameworks/base/core/proto/android/service/sensor_service.proto
|
||
|
*/
|
||
|
void SensorList::dump(util::ProtoOutputStream* proto) const {
|
||
|
using namespace service::SensorListProto;
|
||
|
using namespace service::SensorListProto::SensorProto;
|
||
|
|
||
|
forEachSensor([&proto] (const Sensor& s) -> bool {
|
||
|
const uint64_t token = proto->start(SENSORS);
|
||
|
proto->write(HANDLE, s.getHandle());
|
||
|
proto->write(NAME, std::string(s.getName().string()));
|
||
|
proto->write(VENDOR, std::string(s.getVendor().string()));
|
||
|
proto->write(VERSION, s.getVersion());
|
||
|
proto->write(STRING_TYPE, std::string(s.getStringType().string()));
|
||
|
proto->write(TYPE, s.getType());
|
||
|
proto->write(REQUIRED_PERMISSION, std::string(s.getRequiredPermission().size() ?
|
||
|
s.getRequiredPermission().string() : ""));
|
||
|
proto->write(FLAGS, int(s.getFlags()));
|
||
|
switch (s.getReportingMode()) {
|
||
|
case AREPORTING_MODE_CONTINUOUS:
|
||
|
proto->write(REPORTING_MODE, RM_CONTINUOUS);
|
||
|
break;
|
||
|
case AREPORTING_MODE_ON_CHANGE:
|
||
|
proto->write(REPORTING_MODE, RM_ON_CHANGE);
|
||
|
break;
|
||
|
case AREPORTING_MODE_ONE_SHOT:
|
||
|
proto->write(REPORTING_MODE, RM_ONE_SHOT);
|
||
|
break;
|
||
|
case AREPORTING_MODE_SPECIAL_TRIGGER:
|
||
|
proto->write(REPORTING_MODE, RM_SPECIAL_TRIGGER);
|
||
|
break;
|
||
|
default:
|
||
|
proto->write(REPORTING_MODE, RM_UNKNOWN);
|
||
|
}
|
||
|
proto->write(MAX_DELAY_US, s.getMaxDelay());
|
||
|
proto->write(MIN_DELAY_US, s.getMinDelay());
|
||
|
proto->write(FIFO_MAX_EVENT_COUNT, int(s.getFifoMaxEventCount()));
|
||
|
proto->write(FIFO_RESERVED_EVENT_COUNT, int(s.getFifoReservedEventCount()));
|
||
|
proto->write(IS_WAKEUP, s.isWakeUpSensor());
|
||
|
proto->write(DATA_INJECTION_SUPPORTED, s.isDataInjectionSupported());
|
||
|
proto->write(IS_DYNAMIC, s.isDynamicSensor());
|
||
|
proto->write(HAS_ADDITIONAL_INFO, s.hasAdditionalInfo());
|
||
|
proto->write(HIGHEST_RATE_LEVEL, s.getHighestDirectReportRateLevel());
|
||
|
proto->write(ASHMEM, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM));
|
||
|
proto->write(GRALLOC, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC));
|
||
|
proto->write(MIN_VALUE, s.getMinValue());
|
||
|
proto->write(MAX_VALUE, s.getMaxValue());
|
||
|
proto->write(RESOLUTION, s.getResolution());
|
||
|
proto->write(POWER_USAGE, s.getPowerUsage());
|
||
|
proto->end(token);
|
||
|
return true;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
SensorList::~SensorList() {
|
||
|
}
|
||
|
|
||
|
} // namespace SensorServiceUtil
|
||
|
} // namespace android
|
||
|
|