1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "SensorList.h"
18 
19 #include <android/util/ProtoOutputStream.h>
20 #include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
21 #include <hardware/sensors.h>
22 #include <utils/String8.h>
23 
24 #include <cinttypes>
25 
26 namespace android {
27 namespace SensorServiceUtil {
28 
29 const Sensor SensorList::mNonSensor = Sensor("unknown");
30 
add(int handle,std::shared_ptr<SensorInterface> si,bool isForDebug,bool isVirtual,int deviceId)31 bool SensorList::add(int handle, std::shared_ptr<SensorInterface> si, bool isForDebug,
32                      bool isVirtual, int deviceId) {
33     std::lock_guard<std::mutex> lk(mLock);
34     if (handle == si->getSensor().getHandle() &&
35         mUsedHandle.insert(handle).second) {
36         // will succeed as the mUsedHandle does not have this handle
37         mHandleMap.emplace(handle, Entry(std::move(si), isForDebug, isVirtual, deviceId));
38         return true;
39     }
40     // handle exist already or handle mismatch
41     return false;
42 }
43 
remove(int handle)44 bool SensorList::remove(int handle) {
45     std::lock_guard<std::mutex> lk(mLock);
46     auto entry = mHandleMap.find(handle);
47     if (entry != mHandleMap.end()) {
48         mHandleMap.erase(entry);
49         return true;
50     }
51     return false;
52 }
53 
getName(int handle) const54 String8 SensorList::getName(int handle) const {
55     return getOne<String8>(
56             handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getName();},
57             mNonSensor.getName());
58 }
59 
getStringType(int handle) const60 String8 SensorList::getStringType(int handle) const {
61     return getOne<String8>(
62             handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getStringType();},
63             mNonSensor.getStringType());
64 }
65 
getInterface(int handle) const66 std::shared_ptr<SensorInterface> SensorList::getInterface(int handle) const {
67     return getOne<std::shared_ptr<SensorInterface>>(
68             handle, [] (const Entry& e) -> std::shared_ptr<SensorInterface> {return e.si;},
69             nullptr);
70 }
71 
isNewHandle(int handle) const72 bool SensorList::isNewHandle(int handle) const {
73     std::lock_guard<std::mutex> lk(mLock);
74     return mUsedHandle.find(handle) == mUsedHandle.end();
75 }
76 
getUserSensors() const77 const Vector<Sensor> SensorList::getUserSensors() const {
78     // lock in forEachEntry
79     Vector<Sensor> sensors;
80     forEachEntry(
81             [&sensors] (const Entry& e) -> bool {
82                 if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()
83                     && e.deviceId == RuntimeSensor::DEFAULT_DEVICE_ID) {
84                     sensors.add(e.si->getSensor());
85                 }
86                 return true;
87             });
88     return sensors;
89 }
90 
getUserDebugSensors() const91 const Vector<Sensor> SensorList::getUserDebugSensors() const {
92     // lock in forEachEntry
93     Vector<Sensor> sensors;
94     forEachEntry(
95             [&sensors] (const Entry& e) -> bool {
96                 if (!e.si->getSensor().isDynamicSensor()
97                     && e.deviceId == RuntimeSensor::DEFAULT_DEVICE_ID) {
98                     sensors.add(e.si->getSensor());
99                 }
100                 return true;
101             });
102     return sensors;
103 }
104 
getDynamicSensors() const105 const Vector<Sensor> SensorList::getDynamicSensors() const {
106     // lock in forEachEntry
107     Vector<Sensor> sensors;
108     forEachEntry(
109             [&sensors] (const Entry& e) -> bool {
110                 if (!e.isForDebug && e.si->getSensor().isDynamicSensor()
111                      && e.deviceId == RuntimeSensor::DEFAULT_DEVICE_ID) {
112                     sensors.add(e.si->getSensor());
113                 }
114                 return true;
115             });
116     return sensors;
117 }
118 
getVirtualSensors() const119 const Vector<Sensor> SensorList::getVirtualSensors() const {
120     // lock in forEachEntry
121     Vector<Sensor> sensors;
122     forEachEntry(
123             [&sensors] (const Entry& e) -> bool {
124                 if (e.isVirtual && e.deviceId == RuntimeSensor::DEFAULT_DEVICE_ID) {
125                     sensors.add(e.si->getSensor());
126                 }
127                 return true;
128             });
129     return sensors;
130 }
131 
getRuntimeSensors(int deviceId) const132 const Vector<Sensor> SensorList::getRuntimeSensors(int deviceId) const {
133     // lock in forEachEntry
134     Vector<Sensor> sensors;
135     forEachEntry(
136             [&sensors, deviceId] (const Entry& e) -> bool {
137                 if (!e.isForDebug && e.deviceId == deviceId) {
138                     sensors.add(e.si->getSensor());
139                 }
140                 return true;
141             });
142     return sensors;
143 }
144 
dump() const145 std::string SensorList::dump() const {
146     String8 result;
147 
148     forEachSensor([&result] (const Sensor& s) -> bool {
149             result.appendFormat(
150                     "%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
151                         ") | perm: %s | flags: 0x%08x\n",
152                     s.getHandle(),
153                     s.getName().c_str(),
154                     s.getVendor().c_str(),
155                     s.getVersion(),
156                     s.getStringType().c_str(),
157                     s.getType(),
158                     s.getRequiredPermission().size() ? s.getRequiredPermission().c_str() : "n/a",
159                     static_cast<int>(s.getFlags()));
160 
161             result.append("\t");
162             const int reportingMode = s.getReportingMode();
163             if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
164                 result.append("continuous | ");
165             } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
166                 result.append("on-change | ");
167             } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
168                 result.append("one-shot | ");
169             } else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
170                 result.append("special-trigger | ");
171             } else {
172                 result.append("unknown-mode | ");
173             }
174 
175             if (s.getMaxDelay() > 0) {
176                 result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
177             } else {
178                 result.appendFormat("maxDelay=%" PRId32 "us | ", s.getMaxDelay());
179             }
180 
181             if (s.getMinDelay() > 0) {
182                 result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
183             } else {
184                 result.appendFormat("minDelay=%" PRId32 "us | ", s.getMinDelay());
185             }
186 
187             if (s.getFifoMaxEventCount() > 0) {
188                 result.appendFormat("FIFO (max,reserved) = (%" PRIu32 ", %" PRIu32 ") events | ",
189                         s.getFifoMaxEventCount(),
190                         s.getFifoReservedEventCount());
191             } else {
192                 result.append("no batching | ");
193             }
194 
195             if (s.isWakeUpSensor()) {
196                 result.appendFormat("wakeUp | ");
197             } else {
198                 result.appendFormat("non-wakeUp | ");
199             }
200 
201             if (s.isDataInjectionSupported()) {
202                 result.appendFormat("data-injection, ");
203             }
204 
205             if (s.isDynamicSensor()) {
206                 result.appendFormat("dynamic, ");
207             }
208 
209             if (s.hasAdditionalInfo()) {
210                 result.appendFormat("has-additional-info, ");
211             }
212             result.append("\n");
213 
214             if (s.getHighestDirectReportRateLevel() > SENSOR_DIRECT_RATE_STOP) {
215                 result.appendFormat("\thighest rate level = %d, support shared mem: ",
216                         s.getHighestDirectReportRateLevel());
217                 if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM)) {
218                     result.append("ashmem, ");
219                 }
220                 if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)) {
221                     result.append("gralloc, ");
222                 }
223                 result.append("\n");
224             }
225             return true;
226         });
227     return std::string(result.c_str());
228 }
229 
230 /**
231  * Dump debugging information as android.service.SensorListProto protobuf message using
232  * ProtoOutputStream.
233  *
234  * See proto definition and some notes about ProtoOutputStream in
235  * frameworks/base/core/proto/android/service/sensor_service.proto
236  */
dump(util::ProtoOutputStream * proto) const237 void SensorList::dump(util::ProtoOutputStream* proto) const {
238     using namespace service::SensorListProto;
239     using namespace service::SensorListProto::SensorProto;
240 
241     forEachSensor([&proto] (const Sensor& s) -> bool {
242         const uint64_t token = proto->start(SENSORS);
243         proto->write(HANDLE, s.getHandle());
244         proto->write(NAME, std::string(s.getName().c_str()));
245         proto->write(VENDOR, std::string(s.getVendor().c_str()));
246         proto->write(VERSION, s.getVersion());
247         proto->write(STRING_TYPE, std::string(s.getStringType().c_str()));
248         proto->write(TYPE, s.getType());
249         proto->write(REQUIRED_PERMISSION, std::string(s.getRequiredPermission().size() ?
250                 s.getRequiredPermission().c_str() : ""));
251         proto->write(FLAGS, int(s.getFlags()));
252         switch (s.getReportingMode()) {
253             case AREPORTING_MODE_CONTINUOUS:
254                 proto->write(REPORTING_MODE, RM_CONTINUOUS);
255                 break;
256             case AREPORTING_MODE_ON_CHANGE:
257                 proto->write(REPORTING_MODE, RM_ON_CHANGE);
258                 break;
259             case AREPORTING_MODE_ONE_SHOT:
260                 proto->write(REPORTING_MODE, RM_ONE_SHOT);
261                 break;
262             case AREPORTING_MODE_SPECIAL_TRIGGER:
263                 proto->write(REPORTING_MODE, RM_SPECIAL_TRIGGER);
264                 break;
265             default:
266                 proto->write(REPORTING_MODE, RM_UNKNOWN);
267         }
268         proto->write(MAX_DELAY_US, s.getMaxDelay());
269         proto->write(MIN_DELAY_US, s.getMinDelay());
270         proto->write(FIFO_MAX_EVENT_COUNT, int(s.getFifoMaxEventCount()));
271         proto->write(FIFO_RESERVED_EVENT_COUNT, int(s.getFifoReservedEventCount()));
272         proto->write(IS_WAKEUP, s.isWakeUpSensor());
273         proto->write(DATA_INJECTION_SUPPORTED, s.isDataInjectionSupported());
274         proto->write(IS_DYNAMIC, s.isDynamicSensor());
275         proto->write(HAS_ADDITIONAL_INFO, s.hasAdditionalInfo());
276         proto->write(HIGHEST_RATE_LEVEL, s.getHighestDirectReportRateLevel());
277         proto->write(ASHMEM, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM));
278         proto->write(GRALLOC, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC));
279         proto->write(MIN_VALUE, s.getMinValue());
280         proto->write(MAX_VALUE, s.getMaxValue());
281         proto->write(RESOLUTION, s.getResolution());
282         proto->write(POWER_USAGE, s.getPowerUsage());
283         proto->end(token);
284         return true;
285     });
286 }
287 
~SensorList()288 SensorList::~SensorList() {
289 }
290 
291 } // namespace SensorServiceUtil
292 } // namespace android
293 
294