diff options
author | 2020-01-29 00:36:55 -0800 | |
---|---|---|
committer | 2020-02-05 11:41:51 -0800 | |
commit | 2474386851ae14b62435ebc2befffdf3859963ac (patch) | |
tree | 73c42e65088e8f4dae07482f73aba246ac9f7749 | |
parent | 2068b3fce1cae72957dced91ea35578a8a690128 (diff) |
Dumpsys sensorservice --proto
Add protobuf dumpsys of sensorservice. Primarily used by incident
service to capture an incident report proto.
Command to invoke (any of the following after lunch and env setup):
$ adb shell dumpsys sensorservice --proto
$ adb shell incident 3053
$ incident_report 3053
Bug: 146086105
Test: Execute the above commands and compare the output against dumpsys
sensorservice
Change-Id: I9d7af7d4bc25fa485bbc2933fbb8322307780989
-rw-r--r-- | services/sensorservice/Android.bp | 3 | ||||
-rw-r--r-- | services/sensorservice/RecentEventLogger.cpp | 36 | ||||
-rw-r--r-- | services/sensorservice/RecentEventLogger.h | 1 | ||||
-rw-r--r-- | services/sensorservice/SensorDevice.cpp | 40 | ||||
-rw-r--r-- | services/sensorservice/SensorDevice.h | 3 | ||||
-rw-r--r-- | services/sensorservice/SensorDirectConnection.cpp | 25 | ||||
-rw-r--r-- | services/sensorservice/SensorDirectConnection.h | 1 | ||||
-rw-r--r-- | services/sensorservice/SensorEventConnection.cpp | 47 | ||||
-rw-r--r-- | services/sensorservice/SensorEventConnection.h | 1 | ||||
-rw-r--r-- | services/sensorservice/SensorFusion.cpp | 42 | ||||
-rw-r--r-- | services/sensorservice/SensorFusion.h | 4 | ||||
-rw-r--r-- | services/sensorservice/SensorList.cpp | 60 | ||||
-rw-r--r-- | services/sensorservice/SensorList.h | 1 | ||||
-rw-r--r-- | services/sensorservice/SensorRegistrationInfo.h | 55 | ||||
-rw-r--r-- | services/sensorservice/SensorService.cpp | 122 | ||||
-rw-r--r-- | services/sensorservice/SensorService.h | 1 | ||||
-rw-r--r-- | services/sensorservice/SensorServiceUtils.h | 6 |
17 files changed, 429 insertions, 19 deletions
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp index 1c9a4af72b..5246c78866 100644 --- a/services/sensorservice/Android.bp +++ b/services/sensorservice/Android.bp @@ -42,6 +42,7 @@ cc_library_shared { "libbinder", "libsensor", "libsensorprivacy", + "libprotoutil", "libcrypto", "libbase", "libhidlbase", @@ -52,6 +53,8 @@ cc_library_shared { static_libs: ["android.hardware.sensors@1.0-convert"], + generated_headers: ["framework-cppstream-protos"], + // our public headers depend on libsensor and libsensorprivacy export_shared_lib_headers: ["libsensor", "libsensorprivacy"], } diff --git a/services/sensorservice/RecentEventLogger.cpp b/services/sensorservice/RecentEventLogger.cpp index 207b09711a..d7ca6e1dbf 100644 --- a/services/sensorservice/RecentEventLogger.cpp +++ b/services/sensorservice/RecentEventLogger.cpp @@ -17,6 +17,8 @@ #include "RecentEventLogger.h" #include "SensorServiceUtils.h" +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h> #include <utils/Timers.h> #include <inttypes.h> @@ -84,6 +86,40 @@ std::string RecentEventLogger::dump() const { return std::string(buffer.string()); } +/** + * Dump debugging information as android.service.SensorEventsProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void RecentEventLogger::dump(util::ProtoOutputStream* proto) const { + using namespace service::SensorEventsProto; + std::lock_guard<std::mutex> lk(mLock); + + proto->write(RecentEventsLog::RECENT_EVENTS_COUNT, int(mRecentEvents.size())); + for (int i = mRecentEvents.size() - 1; i >= 0; --i) { + const auto& ev = mRecentEvents[i]; + const uint64_t token = proto->start(RecentEventsLog::EVENTS); + proto->write(Event::TIMESTAMP_SEC, float(ev.mEvent.timestamp) / 1e9f); + proto->write(Event::WALL_TIMESTAMP_MS, ev.mWallTime.tv_sec * 1000LL + + ns2ms(ev.mWallTime.tv_nsec)); + + if (mMaskData) { + proto->write(Event::MASKED, true); + } else { + if (mSensorType == SENSOR_TYPE_STEP_COUNTER) { + proto->write(Event::INT64_DATA, int64_t(ev.mEvent.u64.step_counter)); + } else { + for (size_t k = 0; k < mEventSize; ++k) { + proto->write(Event::FLOAT_ARRAY, ev.mEvent.data[k]); + } + } + } + proto->end(token); + } +} + void RecentEventLogger::setFormat(std::string format) { if (format == "mask_data" ) { mMaskData = true; diff --git a/services/sensorservice/RecentEventLogger.h b/services/sensorservice/RecentEventLogger.h index 67378b7dd6..3a2ae77fc8 100644 --- a/services/sensorservice/RecentEventLogger.h +++ b/services/sensorservice/RecentEventLogger.h @@ -48,6 +48,7 @@ public: // Dumpable interface virtual std::string dump() const override; + virtual void dump(util::ProtoOutputStream* proto) const override; virtual void setFormat(std::string format) override; protected: diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index c7a8f5bee3..33f940fe80 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -21,6 +21,8 @@ #include "SensorService.h" #include <android-base/logging.h> +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h> #include <sensors/convert.h> #include <cutils/atomic.h> #include <utils/Errors.h> @@ -39,6 +41,7 @@ using android::hardware::sensors::V2_0::WakeLockQueueFlagBits; using android::hardware::hidl_vec; using android::hardware::Return; using android::SensorDeviceUtils::HidlServiceRegistrationWaiter; +using android::util::ProtoOutputStream; namespace android { // --------------------------------------------------------------------------- @@ -396,6 +399,43 @@ std::string SensorDevice::dump() const { return result.string(); } +/** + * Dump debugging information as android.service.SensorDeviceProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void SensorDevice::dump(ProtoOutputStream* proto) const { + using namespace service::SensorDeviceProto; + if (mSensors == nullptr) { + proto->write(INITIALIZED , false); + return; + } + proto->write(INITIALIZED , true); + proto->write(TOTAL_SENSORS , int(mSensorList.size())); + proto->write(ACTIVE_SENSORS , int(mActivationCount.size())); + + Mutex::Autolock _l(mLock); + for (const auto & s : mSensorList) { + int32_t handle = s.handle; + const Info& info = mActivationCount.valueFor(handle); + if (info.numActiveClients() == 0) continue; + + uint64_t token = proto->start(SENSORS); + proto->write(SensorProto::HANDLE , handle); + proto->write(SensorProto::ACTIVE_COUNT , int(info.batchParams.size())); + for (size_t j = 0; j < info.batchParams.size(); j++) { + const BatchParams& params = info.batchParams[j]; + proto->write(SensorProto::SAMPLING_PERIOD_MS , params.mTSample / 1e6f); + proto->write(SensorProto::BATCHING_PERIOD_MS , params.mTBatch / 1e6f); + } + proto->write(SensorProto::SAMPLING_PERIOD_SELECTED , info.bestBatchParams.mTSample / 1e6f); + proto->write(SensorProto::BATCHING_PERIOD_SELECTED , info.bestBatchParams.mTBatch / 1e6f); + proto->end(token); + } +} + ssize_t SensorDevice::getSensorList(sensor_t const** list) { *list = &mSensorList[0]; diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h index d2c6994023..33aa7d64b0 100644 --- a/services/sensorservice/SensorDevice.h +++ b/services/sensorservice/SensorDevice.h @@ -123,7 +123,8 @@ public: bool isSensorActive(int handle) const; // Dumpable - virtual std::string dump() const; + virtual std::string dump() const override; + virtual void dump(util::ProtoOutputStream* proto) const override; private: friend class Singleton<SensorDevice>; diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp index cd0ea5d22c..106efd6634 100644 --- a/services/sensorservice/SensorDirectConnection.cpp +++ b/services/sensorservice/SensorDirectConnection.cpp @@ -16,12 +16,16 @@ #include "SensorDevice.h" #include "SensorDirectConnection.h" +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h> #include <hardware/sensors.h> #define UNUSED(x) (void)(x) namespace android { +using util::ProtoOutputStream; + SensorService::SensorDirectConnection::SensorDirectConnection(const sp<SensorService>& service, uid_t uid, const sensors_direct_mem_t *mem, int32_t halChannelHandle, const String16& opPackageName) @@ -64,6 +68,27 @@ void SensorService::SensorDirectConnection::dump(String8& result) const { } } +/** + * Dump debugging information as android.service.SensorDirectConnectionProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void SensorService::SensorDirectConnection::dump(ProtoOutputStream* proto) const { + using namespace service::SensorDirectConnectionProto; + Mutex::Autolock _l(mConnectionLock); + proto->write(PACKAGE_NAME, std::string(String8(mOpPackageName).string())); + proto->write(HAL_CHANNEL_HANDLE, getHalChannelHandle()); + proto->write(NUM_SENSOR_ACTIVATED, int(mActivated.size())); + for (auto &i : mActivated) { + uint64_t token = proto->start(SENSORS); + proto->write(SensorProto::SENSOR, i.first); + proto->write(SensorProto::RATE, i.second); + proto->end(token); + } +} + sp<BitTube> SensorService::SensorDirectConnection::getSensorChannel() const { return nullptr; } diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h index 5c398a8caa..ead08d3fb6 100644 --- a/services/sensorservice/SensorDirectConnection.h +++ b/services/sensorservice/SensorDirectConnection.h @@ -40,6 +40,7 @@ public: const sensors_direct_mem_t *mem, int32_t halChannelHandle, const String16& opPackageName); void dump(String8& result) const; + void dump(util::ProtoOutputStream* proto) const; uid_t getUid() const { return mUid; } int32_t getHalChannelHandle() const; bool isEquivalent(const sensors_direct_mem_t *mem) const; diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp index 0e409409f2..9a13c00664 100644 --- a/services/sensorservice/SensorEventConnection.cpp +++ b/services/sensorservice/SensorEventConnection.cpp @@ -17,6 +17,8 @@ #include <sys/socket.h> #include <utils/threads.h> +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h> #include <sensor/SensorEventQueue.h> #include "vec.h" @@ -110,6 +112,51 @@ void SensorService::SensorEventConnection::dump(String8& result) { #endif } +/** + * Dump debugging information as android.service.SensorEventConnectionProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void SensorService::SensorEventConnection::dump(util::ProtoOutputStream* proto) const { + using namespace service::SensorEventConnectionProto; + Mutex::Autolock _l(mConnectionLock); + + if (!mService->isWhiteListedPackage(getPackageName())) { + proto->write(OPERATING_MODE, OP_MODE_RESTRICTED); + } else if (mDataInjectionMode) { + proto->write(OPERATING_MODE, OP_MODE_DATA_INJECTION); + } else { + proto->write(OPERATING_MODE, OP_MODE_NORMAL); + } + proto->write(PACKAGE_NAME, std::string(mPackageName.string())); + proto->write(WAKE_LOCK_REF_COUNT, int32_t(mWakeLockRefCount)); + proto->write(UID, int32_t(mUid)); + proto->write(CACHE_SIZE, int32_t(mCacheSize)); + proto->write(MAX_CACHE_SIZE, int32_t(mMaxCacheSize)); + for (size_t i = 0; i < mSensorInfo.size(); ++i) { + const FlushInfo& flushInfo = mSensorInfo.valueAt(i); + const uint64_t token = proto->start(FLUSH_INFOS); + proto->write(FlushInfoProto::SENSOR_NAME, + std::string(mService->getSensorName(mSensorInfo.keyAt(i)))); + proto->write(FlushInfoProto::SENSOR_HANDLE, mSensorInfo.keyAt(i)); + proto->write(FlushInfoProto::FIRST_FLUSH_PENDING, flushInfo.mFirstFlushPending); + proto->write(FlushInfoProto::PENDING_FLUSH_EVENTS_TO_SEND, + flushInfo.mPendingFlushEventsToSend); + proto->end(token); + } +#if DEBUG_CONNECTIONS + proto->write(EVENTS_RECEIVED, mEventsReceived); + proto->write(EVENTS_SENT, mEventsSent); + proto->write(EVENTS_CACHE, mEventsSentFromCache); + proto->write(EVENTS_DROPPED, mEventsReceived - (mEventsSentFromCache + mEventsSent + + mCacheSize)); + proto->write(TOTAL_ACKS_NEEDED, mTotalAcksNeeded); + proto->write(TOTAL_ACKS_RECEIVED, mTotalAcksReceived); +#endif +} + bool SensorService::SensorEventConnection::addSensor(int32_t handle) { Mutex::Autolock _l(mConnectionLock); sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle); diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h index fd881cbc0b..caf5d7c9d9 100644 --- a/services/sensorservice/SensorEventConnection.h +++ b/services/sensorservice/SensorEventConnection.h @@ -62,6 +62,7 @@ public: bool removeSensor(int32_t handle); void setFirstFlushPending(int32_t handle, bool value); void dump(String8& result); + void dump(util::ProtoOutputStream* proto) const; bool needsWakeLock(); void resetWakeLockRefCount(); String8 getPackageName() const; diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp index 414f673271..e27b52b23e 100644 --- a/services/sensorservice/SensorFusion.cpp +++ b/services/sensorservice/SensorFusion.cpp @@ -18,6 +18,9 @@ #include "SensorFusion.h" #include "SensorService.h" +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h> + namespace android { // --------------------------------------------------------------------------- @@ -183,7 +186,7 @@ int32_t SensorFusion::getMinDelay() const { return mAcc.getMinDelay(); } -void SensorFusion::dump(String8& result) { +void SensorFusion::dump(String8& result) const { const Fusion& fusion_9axis(mFusions[FUSION_9AXIS]); result.appendFormat("9-axis fusion %s (%zd clients), gyro-rate=%7.2fHz, " "q=< %g, %g, %g, %g > (%g), " @@ -235,5 +238,42 @@ void SensorFusion::dump(String8& result) { fusion_nogyro.getBias().z); } +void SensorFusion::dumpFusion(FUSION_MODE mode, util::ProtoOutputStream* proto) const { + using namespace service::SensorFusionProto::FusionProto; + const Fusion& fusion(mFusions[mode]); + proto->write(ENABLED, mEnabled[mode]); + proto->write(NUM_CLIENTS, (int)mClients[mode].size()); + proto->write(ESTIMATED_GYRO_RATE, mEstimatedGyroRate); + proto->write(ATTITUDE_X, fusion.getAttitude().x); + proto->write(ATTITUDE_Y, fusion.getAttitude().y); + proto->write(ATTITUDE_Z, fusion.getAttitude().z); + proto->write(ATTITUDE_W, fusion.getAttitude().w); + proto->write(ATTITUDE_LENGTH, length(fusion.getAttitude())); + proto->write(BIAS_X, fusion.getBias().x); + proto->write(BIAS_Y, fusion.getBias().y); + proto->write(BIAS_Z, fusion.getBias().z); +} + +/** + * Dump debugging information as android.service.SensorFusionProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void SensorFusion::dump(util::ProtoOutputStream* proto) const { + uint64_t token = proto->start(service::SensorFusionProto::FUSION_9AXIS); + dumpFusion(FUSION_9AXIS, proto); + proto->end(token); + + token = proto->start(service::SensorFusionProto::FUSION_NOMAG); + dumpFusion(FUSION_NOMAG, proto); + proto->end(token); + + token = proto->start(service::SensorFusionProto::FUSION_NOGYRO); + dumpFusion(FUSION_NOGYRO, proto); + proto->end(token); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h index 8c0fbf9a6e..66a72902cc 100644 --- a/services/sensorservice/SensorFusion.h +++ b/services/sensorservice/SensorFusion.h @@ -90,7 +90,9 @@ public: float getPowerUsage(int mode=FUSION_9AXIS) const; int32_t getMinDelay() const; - void dump(String8& result); + void dump(String8& result) const; + void dump(util::ProtoOutputStream* proto) const; + void dumpFusion(FUSION_MODE mode, util::ProtoOutputStream* proto) const; }; diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp index aa306d885e..0ce32cc06f 100644 --- a/services/sensorservice/SensorList.cpp +++ b/services/sensorservice/SensorList.cpp @@ -16,6 +16,8 @@ #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> @@ -203,6 +205,64 @@ std::string SensorList::dump() const { 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() { } diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h index 6b90ad99f9..8424b22ed2 100644 --- a/services/sensorservice/SensorList.h +++ b/services/sensorservice/SensorList.h @@ -71,6 +71,7 @@ public: // Dumpable interface virtual std::string dump() const override; + virtual void dump(util::ProtoOutputStream* proto) const override; virtual ~SensorList(); private: diff --git a/services/sensorservice/SensorRegistrationInfo.h b/services/sensorservice/SensorRegistrationInfo.h index 5411515d49..a34a65bbdd 100644 --- a/services/sensorservice/SensorRegistrationInfo.h +++ b/services/sensorservice/SensorRegistrationInfo.h @@ -17,10 +17,14 @@ #ifndef ANDROID_SENSOR_REGISTRATION_INFO_H #define ANDROID_SENSOR_REGISTRATION_INFO_H -#include "SensorServiceUtils.h" -#include <utils/Thread.h> +#include <ctime> #include <iomanip> #include <sstream> +#include <utils/Thread.h> + +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h> +#include "SensorServiceUtils.h" namespace android { @@ -30,7 +34,7 @@ class SensorService::SensorRegistrationInfo : public SensorServiceUtil::Dumpable public: SensorRegistrationInfo() : mPackageName() { mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN; - mHour = mMin = mSec = INT8_MIN; + mRealtimeSec = 0; mActivated = false; } @@ -47,25 +51,26 @@ public: mPid = (thread != nullptr) ? thread->getCallingPid() : -1; mUid = (thread != nullptr) ? thread->getCallingUid() : -1; - time_t rawtime = time(nullptr); - struct tm * timeinfo = localtime(&rawtime); - mHour = static_cast<int8_t>(timeinfo->tm_hour); - mMin = static_cast<int8_t>(timeinfo->tm_min); - mSec = static_cast<int8_t>(timeinfo->tm_sec); + timespec curTime; + clock_gettime(CLOCK_REALTIME_COARSE, &curTime); + mRealtimeSec = curTime.tv_sec; } static bool isSentinel(const SensorRegistrationInfo& info) { - return (info.mHour == INT8_MIN && - info.mMin == INT8_MIN && - info.mSec == INT8_MIN); + return (info.mSensorHandle == INT32_MIN && info.mRealtimeSec == 0); } // Dumpable interface virtual std::string dump() const override { + struct tm* timeinfo = localtime(&mRealtimeSec); + const int8_t hour = static_cast<int8_t>(timeinfo->tm_hour); + const int8_t min = static_cast<int8_t>(timeinfo->tm_min); + const int8_t sec = static_cast<int8_t>(timeinfo->tm_sec); + std::ostringstream ss; - ss << std::setfill('0') << std::setw(2) << static_cast<int>(mHour) << ":" - << std::setw(2) << static_cast<int>(mMin) << ":" - << std::setw(2) << static_cast<int>(mSec) + ss << std::setfill('0') << std::setw(2) << static_cast<int>(hour) << ":" + << std::setw(2) << static_cast<int>(min) << ":" + << std::setw(2) << static_cast<int>(sec) << (mActivated ? " +" : " -") << " 0x" << std::hex << std::setw(8) << mSensorHandle << std::dec << std::setfill(' ') << " pid=" << std::setw(5) << mPid @@ -77,6 +82,25 @@ public: return ss.str(); } + /** + * Dump debugging information as android.service.SensorRegistrationInfoProto protobuf message + * using ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ + virtual void dump(util::ProtoOutputStream* proto) const override { + using namespace service::SensorRegistrationInfoProto; + proto->write(TIMESTAMP_SEC, int64_t(mRealtimeSec)); + proto->write(SENSOR_HANDLE, mSensorHandle); + proto->write(PACKAGE_NAME, std::string(mPackageName.string())); + proto->write(PID, int32_t(mPid)); + proto->write(UID, int32_t(mUid)); + proto->write(SAMPLING_RATE_US, mSamplingRateUs); + proto->write(MAX_REPORT_LATENCY_US, mMaxReportLatencyUs); + proto->write(ACTIVATED, mActivated); + } + private: int32_t mSensorHandle; String8 mPackageName; @@ -85,8 +109,7 @@ private: int64_t mSamplingRateUs; int64_t mMaxReportLatencyUs; bool mActivated; - int8_t mHour, mMin, mSec; - + time_t mRealtimeSec; }; } // namespace android; diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index c2e1204b87..e803c9ad7e 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ #include <android/content/pm/IPackageManagerNative.h> +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h> #include <binder/ActivityManager.h> #include <binder/BinderService.h> #include <binder/IServiceManager.h> @@ -404,6 +406,8 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) { // Transition to data injection mode supported only from NORMAL mode. return INVALID_OPERATION; } + } else if (args.size() == 1 && args[0] == String16("--proto")) { + return dumpProtoLocked(fd, &connLock); } else if (!mSensors.hasAnySensor()) { result.append("No Sensors on the device\n"); result.appendFormat("devInitCheck : %d\n", SensorDevice::getInstance().initCheck()); @@ -506,6 +510,124 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) { return NO_ERROR; } +/** + * Dump debugging information as android.service.SensorServiceProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +status_t SensorService::dumpProtoLocked(int fd, ConnectionSafeAutolock* connLock) const { + using namespace service::SensorServiceProto; + util::ProtoOutputStream proto; + const bool privileged = IPCThreadState::self()->getCallingUid() == 0; + + timespec curTime; + clock_gettime(CLOCK_REALTIME, &curTime); + proto.write(CURRENT_TIME_MS, curTime.tv_sec * 1000 + ns2ms(curTime.tv_nsec)); + + // Write SensorDeviceProto + uint64_t token = proto.start(SENSOR_DEVICE); + SensorDevice::getInstance().dump(&proto); + proto.end(token); + + // Write SensorListProto + token = proto.start(SENSORS); + mSensors.dump(&proto); + proto.end(token); + + // Write SensorFusionProto + token = proto.start(FUSION_STATE); + SensorFusion::getInstance().dump(&proto); + proto.end(token); + + // Write SensorEventsProto + token = proto.start(SENSOR_EVENTS); + for (auto&& i : mRecentEvent) { + sp<SensorInterface> s = mSensors.getInterface(i.first); + if (!i.second->isEmpty()) { + i.second->setFormat(privileged || s->getSensor().getRequiredPermission().isEmpty() ? + "normal" : "mask_data"); + const uint64_t mToken = proto.start(service::SensorEventsProto::RECENT_EVENTS_LOGS); + proto.write(service::SensorEventsProto::RecentEventsLog::NAME, + std::string(s->getSensor().getName().string())); + i.second->dump(&proto); + proto.end(mToken); + } + } + proto.end(token); + + // Write ActiveSensorProto + SensorDevice& dev = SensorDevice::getInstance(); + for (size_t i=0 ; i<mActiveSensors.size() ; i++) { + int handle = mActiveSensors.keyAt(i); + if (dev.isSensorActive(handle)) { + token = proto.start(ACTIVE_SENSORS); + proto.write(service::ActiveSensorProto::NAME, + std::string(getSensorName(handle).string())); + proto.write(service::ActiveSensorProto::HANDLE, handle); + proto.write(service::ActiveSensorProto::NUM_CONNECTIONS, + int(mActiveSensors.valueAt(i)->getNumConnections())); + proto.end(token); + } + } + + proto.write(SOCKET_BUFFER_SIZE, int(mSocketBufferSize)); + proto.write(SOCKET_BUFFER_SIZE_IN_EVENTS, int(mSocketBufferSize / sizeof(sensors_event_t))); + proto.write(WAKE_LOCK_ACQUIRED, mWakeLockAcquired); + + switch(mCurrentOperatingMode) { + case NORMAL: + proto.write(OPERATING_MODE, OP_MODE_NORMAL); + break; + case RESTRICTED: + proto.write(OPERATING_MODE, OP_MODE_RESTRICTED); + proto.write(WHITELISTED_PACKAGE, std::string(mWhiteListedPackage.string())); + break; + case DATA_INJECTION: + proto.write(OPERATING_MODE, OP_MODE_DATA_INJECTION); + proto.write(WHITELISTED_PACKAGE, std::string(mWhiteListedPackage.string())); + break; + default: + proto.write(OPERATING_MODE, OP_MODE_UNKNOWN); + } + proto.write(SENSOR_PRIVACY, mSensorPrivacyPolicy->isSensorPrivacyEnabled()); + + // Write repeated SensorEventConnectionProto + const auto& activeConnections = connLock->getActiveConnections(); + for (size_t i = 0; i < activeConnections.size(); i++) { + token = proto.start(ACTIVE_CONNECTIONS); + activeConnections[i]->dump(&proto); + proto.end(token); + } + + // Write repeated SensorDirectConnectionProto + const auto& directConnections = connLock->getDirectConnections(); + for (size_t i = 0 ; i < directConnections.size() ; i++) { + token = proto.start(DIRECT_CONNECTIONS); + directConnections[i]->dump(&proto); + proto.end(token); + } + + // Write repeated SensorRegistrationInfoProto + const int startIndex = mNextSensorRegIndex; + int curr = startIndex; + do { + const SensorRegistrationInfo& reg_info = mLastNSensorRegistrations[curr]; + if (SensorRegistrationInfo::isSentinel(reg_info)) { + // Ignore sentinel, proceed to next item. + curr = (curr + 1 + SENSOR_REGISTRATIONS_BUF_SIZE) % SENSOR_REGISTRATIONS_BUF_SIZE; + continue; + } + token = proto.start(PREVIOUS_REGISTRATIONS); + reg_info.dump(&proto); + proto.end(token); + curr = (curr + 1 + SENSOR_REGISTRATIONS_BUF_SIZE) % SENSOR_REGISTRATIONS_BUF_SIZE; + } while (startIndex != curr); + + return proto.flush(fd) ? OK : UNKNOWN_ERROR; +} + void SensorService::disableAllSensors() { ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock); disableAllSensorsLocked(&connLock); diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index fa23da0468..7d17ddabf1 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -286,6 +286,7 @@ private: virtual int setOperationParameter( int32_t handle, int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints); virtual status_t dump(int fd, const Vector<String16>& args); + status_t dumpProtoLocked(int fd, ConnectionSafeAutolock* connLock) const; String8 getSensorName(int handle) const; bool isVirtualSensor(int handle) const; sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const; diff --git a/services/sensorservice/SensorServiceUtils.h b/services/sensorservice/SensorServiceUtils.h index 1558feb75e..49457cf287 100644 --- a/services/sensorservice/SensorServiceUtils.h +++ b/services/sensorservice/SensorServiceUtils.h @@ -21,11 +21,17 @@ #include <string> namespace android { + +namespace util { +class ProtoOutputStream; +} + namespace SensorServiceUtil { class Dumpable { public: virtual std::string dump() const = 0; + virtual void dump(util::ProtoOutputStream*) const {} virtual void setFormat(std::string ) {} virtual ~Dumpable() {} }; |