/* * 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 #include #include #include #include namespace android { namespace SensorServiceUtil { const Sensor SensorList::mNonSensor = Sensor("unknown"); bool SensorList::add( int handle, SensorInterface* si, bool isForDebug, bool isVirtual) { std::lock_guard 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 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( handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getName();}, mNonSensor.getName()); } String8 SensorList::getStringType(int handle) const { return getOne( handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getStringType();}, mNonSensor.getStringType()); } sp SensorList::getInterface(int handle) const { return getOne>( handle, [] (const Entry& e) -> sp {return e.si;}, nullptr); } bool SensorList::isNewHandle(int handle) const { std::lock_guard lk(mLock); return mUsedHandle.find(handle) == mUsedHandle.end(); } const Vector SensorList::getUserSensors() const { // lock in forEachEntry Vector 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 SensorList::getUserDebugSensors() const { // lock in forEachEntry Vector sensors; forEachEntry( [&sensors] (const Entry& e) -> bool { if (!e.si->getSensor().isDynamicSensor()) { sensors.add(e.si->getSensor()); } return true; }); return sensors; } const Vector SensorList::getDynamicSensors() const { // lock in forEachEntry Vector 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 SensorList::getVirtualSensors() const { // lock in forEachEntry Vector 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(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