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,SensorInterface * si,bool isForDebug,bool isVirtual)31 bool SensorList::add(
32         int handle, SensorInterface* si, bool isForDebug, bool isVirtual) {
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(si, isForDebug, isVirtual));
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 
getInterface(int handle) const60 sp<SensorInterface> SensorList::getInterface(int handle) const {
61     return getOne<sp<SensorInterface>>(
62             handle, [] (const Entry& e) -> sp<SensorInterface> {return e.si;}, nullptr);
63 }
64 
65 
isNewHandle(int handle) const66 bool SensorList::isNewHandle(int handle) const {
67     std::lock_guard<std::mutex> lk(mLock);
68     return mUsedHandle.find(handle) == mUsedHandle.end();
69 }
70 
getUserSensors() const71 const Vector<Sensor> SensorList::getUserSensors() const {
72     // lock in forEachEntry
73     Vector<Sensor> sensors;
74     forEachEntry(
75             [&sensors] (const Entry& e) -> bool {
76                 if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()) {
77                     sensors.add(e.si->getSensor());
78                 }
79                 return true;
80             });
81     return sensors;
82 }
83 
getUserDebugSensors() const84 const Vector<Sensor> SensorList::getUserDebugSensors() const {
85     // lock in forEachEntry
86     Vector<Sensor> sensors;
87     forEachEntry(
88             [&sensors] (const Entry& e) -> bool {
89                 if (!e.si->getSensor().isDynamicSensor()) {
90                     sensors.add(e.si->getSensor());
91                 }
92                 return true;
93             });
94     return sensors;
95 }
96 
getDynamicSensors() const97 const Vector<Sensor> SensorList::getDynamicSensors() const {
98     // lock in forEachEntry
99     Vector<Sensor> sensors;
100     forEachEntry(
101             [&sensors] (const Entry& e) -> bool {
102                 if (!e.isForDebug && e.si->getSensor().isDynamicSensor()) {
103                     sensors.add(e.si->getSensor());
104                 }
105                 return true;
106             });
107     return sensors;
108 }
109 
getVirtualSensors() const110 const Vector<Sensor> SensorList::getVirtualSensors() const {
111     // lock in forEachEntry
112     Vector<Sensor> sensors;
113     forEachEntry(
114             [&sensors] (const Entry& e) -> bool {
115                 if (e.isVirtual) {
116                     sensors.add(e.si->getSensor());
117                 }
118                 return true;
119             });
120     return sensors;
121 }
122 
dump() const123 std::string SensorList::dump() const {
124     String8 result;
125 
126     forEachSensor([&result] (const Sensor& s) -> bool {
127             result.appendFormat(
128                     "%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
129                         ") | perm: %s | flags: 0x%08x\n",
130                     s.getHandle(),
131                     s.getName().string(),
132                     s.getVendor().string(),
133                     s.getVersion(),
134                     s.getStringType().string(),
135                     s.getType(),
136                     s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a",
137                     static_cast<int>(s.getFlags()));
138 
139             result.append("\t");
140             const int reportingMode = s.getReportingMode();
141             if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
142                 result.append("continuous | ");
143             } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
144                 result.append("on-change | ");
145             } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
146                 result.append("one-shot | ");
147             } else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
148                 result.append("special-trigger | ");
149             } else {
150                 result.append("unknown-mode | ");
151             }
152 
153             if (s.getMaxDelay() > 0) {
154                 result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
155             } else {
156                 result.appendFormat("maxDelay=%" PRId32 "us | ", s.getMaxDelay());
157             }
158 
159             if (s.getMinDelay() > 0) {
160                 result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
161             } else {
162                 result.appendFormat("minDelay=%" PRId32 "us | ", s.getMinDelay());
163             }
164 
165             if (s.getFifoMaxEventCount() > 0) {
166                 result.appendFormat("FIFO (max,reserved) = (%" PRIu32 ", %" PRIu32 ") events | ",
167                         s.getFifoMaxEventCount(),
168                         s.getFifoReservedEventCount());
169             } else {
170                 result.append("no batching | ");
171             }
172 
173             if (s.isWakeUpSensor()) {
174                 result.appendFormat("wakeUp | ");
175             } else {
176                 result.appendFormat("non-wakeUp | ");
177             }
178 
179             if (s.isDataInjectionSupported()) {
180                 result.appendFormat("data-injection, ");
181             }
182 
183             if (s.isDynamicSensor()) {
184                 result.appendFormat("dynamic, ");
185             }
186 
187             if (s.hasAdditionalInfo()) {
188                 result.appendFormat("has-additional-info, ");
189             }
190             result.append("\n");
191 
192             if (s.getHighestDirectReportRateLevel() > SENSOR_DIRECT_RATE_STOP) {
193                 result.appendFormat("\thighest rate level = %d, support shared mem: ",
194                         s.getHighestDirectReportRateLevel());
195                 if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM)) {
196                     result.append("ashmem, ");
197                 }
198                 if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)) {
199                     result.append("gralloc, ");
200                 }
201                 result.append("\n");
202             }
203             return true;
204         });
205     return std::string(result.string());
206 }
207 
208 /**
209  * Dump debugging information as android.service.SensorListProto protobuf message using
210  * ProtoOutputStream.
211  *
212  * See proto definition and some notes about ProtoOutputStream in
213  * frameworks/base/core/proto/android/service/sensor_service.proto
214  */
dump(util::ProtoOutputStream * proto) const215 void SensorList::dump(util::ProtoOutputStream* proto) const {
216     using namespace service::SensorListProto;
217     using namespace service::SensorListProto::SensorProto;
218 
219     forEachSensor([&proto] (const Sensor& s) -> bool {
220         const uint64_t token = proto->start(SENSORS);
221         proto->write(HANDLE, s.getHandle());
222         proto->write(NAME, std::string(s.getName().string()));
223         proto->write(VENDOR, std::string(s.getVendor().string()));
224         proto->write(VERSION, s.getVersion());
225         proto->write(STRING_TYPE, std::string(s.getStringType().string()));
226         proto->write(TYPE, s.getType());
227         proto->write(REQUIRED_PERMISSION, std::string(s.getRequiredPermission().size() ?
228                 s.getRequiredPermission().string() : ""));
229         proto->write(FLAGS, int(s.getFlags()));
230         switch (s.getReportingMode()) {
231             case AREPORTING_MODE_CONTINUOUS:
232                 proto->write(REPORTING_MODE, RM_CONTINUOUS);
233                 break;
234             case AREPORTING_MODE_ON_CHANGE:
235                 proto->write(REPORTING_MODE, RM_ON_CHANGE);
236                 break;
237             case AREPORTING_MODE_ONE_SHOT:
238                 proto->write(REPORTING_MODE, RM_ONE_SHOT);
239                 break;
240             case AREPORTING_MODE_SPECIAL_TRIGGER:
241                 proto->write(REPORTING_MODE, RM_SPECIAL_TRIGGER);
242                 break;
243             default:
244                 proto->write(REPORTING_MODE, RM_UNKNOWN);
245         }
246         proto->write(MAX_DELAY_US, s.getMaxDelay());
247         proto->write(MIN_DELAY_US, s.getMinDelay());
248         proto->write(FIFO_MAX_EVENT_COUNT, int(s.getFifoMaxEventCount()));
249         proto->write(FIFO_RESERVED_EVENT_COUNT, int(s.getFifoReservedEventCount()));
250         proto->write(IS_WAKEUP, s.isWakeUpSensor());
251         proto->write(DATA_INJECTION_SUPPORTED, s.isDataInjectionSupported());
252         proto->write(IS_DYNAMIC, s.isDynamicSensor());
253         proto->write(HAS_ADDITIONAL_INFO, s.hasAdditionalInfo());
254         proto->write(HIGHEST_RATE_LEVEL, s.getHighestDirectReportRateLevel());
255         proto->write(ASHMEM, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM));
256         proto->write(GRALLOC, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC));
257         proto->write(MIN_VALUE, s.getMinValue());
258         proto->write(MAX_VALUE, s.getMaxValue());
259         proto->write(RESOLUTION, s.getResolution());
260         proto->write(POWER_USAGE, s.getPowerUsage());
261         proto->end(token);
262         return true;
263     });
264 }
265 
~SensorList()266 SensorList::~SensorList() {
267 }
268 
269 } // namespace SensorServiceUtil
270 } // namespace android
271 
272