diff options
-rw-r--r-- | pixelstats/Android.bp | 3 | ||||
-rw-r--r-- | pixelstats/OrientationCollector.cpp | 140 | ||||
-rw-r--r-- | pixelstats/UeventListener.cpp | 35 | ||||
-rw-r--r-- | pixelstats/WlcReporter.cpp | 152 | ||||
-rw-r--r-- | pixelstats/include/pixelstats/OrientationCollector.h | 52 | ||||
-rw-r--r-- | pixelstats/include/pixelstats/UeventListener.h | 4 | ||||
-rw-r--r-- | pixelstats/include/pixelstats/WlcReporter.h | 63 |
7 files changed, 447 insertions, 2 deletions
diff --git a/pixelstats/Android.bp b/pixelstats/Android.bp index d0627aa8..a4ec53b0 100644 --- a/pixelstats/Android.bp +++ b/pixelstats/Android.bp @@ -44,8 +44,10 @@ cc_library { srcs: [ "DropDetect.cpp", + "OrientationCollector.cpp", "SysfsCollector.cpp", "UeventListener.cpp", + "WlcReporter.cpp", ], cflags: [ "-Wall", @@ -59,6 +61,7 @@ cc_library { "libhidlbase", "liblog", "libutils", + "libsensorndkbridge", "pixelatoms-cpp", ], export_shared_lib_headers: [ diff --git a/pixelstats/OrientationCollector.cpp b/pixelstats/OrientationCollector.cpp new file mode 100644 index 00000000..2647a067 --- /dev/null +++ b/pixelstats/OrientationCollector.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "pixelstats-orientation" + +#include <android/sensor.h> +#include <log/log.h> +#include <pixelstats/OrientationCollector.h> + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +#define GET_EVENT_TIMEOUT_MILLIS 200 +#define SENSOR_TYPE_DEVICE_ORIENTATION 27 +#define ORIENTATION_UNKNOWN -1 + +sp<OrientationCollector> OrientationCollector::createOrientationCollector() { + sp<OrientationCollector> orientationCollector; + orientationCollector = new OrientationCollector(); + if (orientationCollector != nullptr && orientationCollector->init() < 0) { + orientationCollector->disableOrientationSensor(); + return nullptr; + } + return orientationCollector; +} + +/* pollOrientation + * orientation: [out] orientation value from sensor Hal. + * Return: OK, or error code from sensor Hal + */ +int32_t OrientationCollector::pollOrientation(int *orientation) { + int err = OK; + int eventCount = 0; + ASensorEvent sensorEvent; + + *orientation = ORIENTATION_UNKNOWN; + /* Get sensor events. */ + /* Get sensor sample events. */ + err = getEvents(&sensorEvent, 1, &eventCount); + if (eventCount > 0) { + ALOGV("%s: ##event data: %f,%f,%f", __func__, sensorEvent.data[0], sensorEvent.data[1], + sensorEvent.data[2]); + *orientation = sensorEvent.data[0]; + } + return err; +} + +/* + * Collects sensor samples and returns them in the sensor sample event list + * specified by event_list. Limits the number of returned sample events to the + * value specified by event_list_size. Returns the number of returned sample + * events in p_event_count. + * + * event_list List of collected sample events. + * event_list_size Size of sample event list. + * event_count Returned count of the number of collected sample + * events. + */ +int OrientationCollector::getEvents(ASensorEvent *event_list, size_t event_list_size, + int *event_count) { + int rv; + int err = OK; + + /* Wait for a sensor event to be available */ + /* The timeout is used to prevent blocking for long time, when sensor pool is + * empty, for example the device is put on a horizontal wireless charger. + */ + rv = ALooper_pollOnce(GET_EVENT_TIMEOUT_MILLIS, nullptr, nullptr, nullptr); + if (rv == ALOOPER_POLL_ERROR) { + ALOGI("Sensor event looper returned a poll error.\n"); + err = UNKNOWN_ERROR; + goto out; + } + + /* Get sensor events. */ + *event_count = ASensorEventQueue_getEvents(mQueue, event_list, event_list_size); + +out: + return err; +} + +int32_t OrientationCollector::init() { + int err = OK; + ALooper *looper = nullptr; + + // Get orientation sensor events from the NDK + mSensorManager = ASensorManager_getInstanceForPackage(nullptr); + if (mSensorManager == nullptr) { + ALOGE("%s: Unable to get sensorManager.\n", __func__); + return UNKNOWN_ERROR; + } + looper = ALooper_forThread(); + if (looper == nullptr) { + looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); + } + if (looper == nullptr) { + ALOGE("%s: Failed to prepare an event looper.\n", __FUNCTION__); + return UNKNOWN_ERROR; + } + mQueue = ASensorManager_createEventQueue(mSensorManager, looper, 0, nullptr, nullptr); + mOrientationSensor = + ASensorManager_getDefaultSensor(mSensorManager, SENSOR_TYPE_DEVICE_ORIENTATION); + if (mOrientationSensor == nullptr) { + ALOGE("%s: Unable to get orientation sensor.\n", __func__); + return UNKNOWN_ERROR; + } + err = ASensorEventQueue_registerSensor(mQueue, mOrientationSensor, + ASensor_getMinDelay(mOrientationSensor), 0); + if (err < 0) { + ALOGE("%s: Unable to register for orientation sensor events\n", __func__); + } + return err; +} + +void OrientationCollector::disableOrientationSensor() { + if (mSensorManager != nullptr && mQueue != nullptr) { + ASensorEventQueue_disableSensor(mQueue, mOrientationSensor); + ASensorManager_destroyEventQueue(mSensorManager, mQueue); + } +} + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android diff --git a/pixelstats/UeventListener.cpp b/pixelstats/UeventListener.cpp index dadfe095..84061bde 100644 --- a/pixelstats/UeventListener.cpp +++ b/pixelstats/UeventListener.cpp @@ -25,6 +25,7 @@ #include <hardware/google/pixel/pixelstats/pixelatoms.pb.h> #include <log/log.h> #include <pixelstats/UeventListener.h> +#include <pixelstats/WlcReporter.h> #include <unistd.h> #include <utils/StrongPointer.h> @@ -37,6 +38,7 @@ using android::frameworks::stats::V1_0::HardwareFailed; using android::frameworks::stats::V1_0::IStats; using android::frameworks::stats::V1_0::UsbPortOverheatEvent; using android::frameworks::stats::V1_0::VendorAtom; +using android::hardware::google::pixel::WlcReporter; using android::hardware::google::pixel::PixelAtoms::ChargeStats; using android::hardware::google::pixel::PixelAtoms::VoltageTierStats; @@ -250,12 +252,29 @@ void UeventListener::ReportChargeMetricsEvent(const char *driver) { } } +/* ReportWlc + * Report wireless relate metrics when wireless charging start + */ +void UeventListener::ReportWlc(const char *driver) { + if (!driver || strncmp(driver, "POWER_SUPPLY_PRESENT=", strlen("POWER_SUPPLY_PRESENT="))) { + return; + } + if (mIsWirelessChargingSupported) { + sp<WlcReporter> wlcReporter = new WlcReporter(); + if (wlcReporter != nullptr) { + mIsWirelessChargingLastState = + wlcReporter->checkAndReport(mIsWirelessChargingLastState); + } + } +} + bool UeventListener::ProcessUevent() { char msg[UEVENT_MSG_LEN + 2]; char *cp; const char *action, *power_supply_typec_mode, *driver, *product; const char *mic_break_status, *mic_degrade_status; const char *devpath; + const char *powpresent; int n; if (uevent_fd_ < 0) { @@ -275,7 +294,7 @@ bool UeventListener::ProcessUevent() { msg[n + 1] = '\0'; action = power_supply_typec_mode = driver = product = NULL; - mic_break_status = mic_degrade_status = devpath = NULL; + mic_break_status = mic_degrade_status = devpath = powpresent = NULL; /** * msg is a sequence of null-terminated strings. @@ -298,6 +317,8 @@ bool UeventListener::ProcessUevent() { mic_degrade_status = cp; } else if (!strncmp(cp, "DEVPATH=", strlen("DEVPATH="))) { devpath = cp; + } else if (!strncmp(cp, "POWER_SUPPLY_PRESENT=", strlen("POWER_SUPPLY_PRESENT="))) { + powpresent = cp; } /* advance to after the next \0 */ @@ -310,6 +331,7 @@ bool UeventListener::ProcessUevent() { ReportMicStatusUevents(devpath, mic_degrade_status); ReportUsbPortOverheatEvent(driver); ReportChargeMetricsEvent(driver); + ReportWlc(powpresent); return true; } @@ -319,13 +341,22 @@ UeventListener::UeventListener(const std::string audio_uevent, const std::string : kAudioUevent(audio_uevent), kUsbPortOverheatPath(overheat_path), kChargeMetricsPath(charge_metrics_path), - uevent_fd_(-1) {} + uevent_fd_(-1), + mIsWirelessChargingLastState(false) {} /* Thread function to continuously monitor uevents. * Exit after kMaxConsecutiveErrors to prevent spinning. */ void UeventListener::ListenForever() { constexpr int kMaxConsecutiveErrors = 10; int consecutive_errors = 0; + sp<WlcReporter> wlcReporter = new WlcReporter(); + if (wlcReporter != nullptr) { + mIsWirelessChargingSupported = wlcReporter->isWlcSupported(); + } else { + ALOGE("Fail to create WlcReporter."); + mIsWirelessChargingSupported = false; + } + while (1) { if (ProcessUevent()) { consecutive_errors = 0; diff --git a/pixelstats/WlcReporter.cpp b/pixelstats/WlcReporter.cpp new file mode 100644 index 00000000..7c9a93f3 --- /dev/null +++ b/pixelstats/WlcReporter.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "pixelstats-wlc" + +#include <android-base/file.h> +#include <log/log.h> +#include <pixelstats/OrientationCollector.h> +#include <pixelstats/WlcReporter.h> + +#define POWER_SUPPLY_SYSFS_PATH "/sys/class/power_supply/wireless/online" +#define POWER_SUPPLY_PTMC_PATH "/sys/class/power_supply/wireless/ptmc_id" +#define GOOGLE_PTMC_ID 72 + +using android::base::ReadFileToString; +using android::frameworks::stats::V1_0::IStats; +using android::frameworks::stats::V1_0::VendorAtom; + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +bool WlcReporter::checkAndReport(bool isWirelessChargingLast) { + bool wireless_charging = isWlcOnline(); + if (wireless_charging && !isWirelessChargingLast) { + doLog(); + } + return wireless_charging; +} + +bool WlcReporter::readFileToInt(const char *const path, int *val) { + std::string file_contents; + + if (!ReadFileToString(path, &file_contents)) { + ALOGE("Unable to read %s - %s", path, strerror(errno)); + return false; + } else if (sscanf(file_contents.c_str(), "%d", val) != 1) { + ALOGE("Unable to convert %s (%s) to int - %s", path, file_contents.c_str(), + strerror(errno)); + return false; + } + return true; +} + +int WlcReporter::readPtmcId() { + int id = 0; + readFileToInt(POWER_SUPPLY_PTMC_PATH, &id); + return id; +} + +/* Reference to frameworks/native/libs/ui/include/ui/DisplayInfo.h + * translate orientation value from sensor to enum define in + * pixelatoms.proto + */ +int WlcReporter::translateDeviceOrientationToAtomValue(int orientation) { + switch (orientation) { + case 0: + return PixelAtoms::DeviceOrientation::ORIENTATION_0; + case 1: + return PixelAtoms::DeviceOrientation::ORIENTATION_90; + case 2: + return PixelAtoms::DeviceOrientation::ORIENTATION_180; + case 3: + return PixelAtoms::DeviceOrientation::ORIENTATION_270; + default: + return PixelAtoms::DeviceOrientation::ORIENTATION_UNKNOWN; + } +} + +void WlcReporter::doLog() { + sp<IStats> stats_client = IStats::tryGetService(); + + if (stats_client == nullptr) { + ALOGE("logWlc get IStats fail."); + return; + } + std::vector<VendorAtom::Value> values(1); + + int vendoriCharger = (readPtmcId() == GOOGLE_PTMC_ID) + ? PixelAtoms::WirelessChargingStats::VENDOR_GOOGLE + : PixelAtoms::WirelessChargingStats::VENDOR_UNKNOWN; + VendorAtom::Value tmp; + tmp.intValue(vendoriCharger); + values[PixelAtoms::WirelessChargingStats::kChargerVendorFieldNumber - kVendorAtomOffset] = tmp; + + // Send vendor atom to IStats HAL + VendorAtom event = {.reverseDomainName = PixelAtoms::ReverseDomainNames().pixel(), + .atomId = PixelAtoms::Ids::WIRELESS_CHARGING_STATS, + .values = values}; + Return<void> retStat = stats_client->reportVendorAtom(event); + if (!retStat.isOk()) + ALOGE("Unable to report WLC_STATS to Stats service"); + + int orientationFromSensor; + sp<OrientationCollector> orientationCollector; + orientationCollector = OrientationCollector::createOrientationCollector(); + if (orientationCollector != nullptr) { + orientationCollector->pollOrientation(&orientationFromSensor); + VendorAtom::Value tmp; + tmp.intValue(translateDeviceOrientationToAtomValue(orientationFromSensor)); + values[PixelAtoms::DeviceOrientation::kOrientationFieldNumber - kVendorAtomOffset] = tmp; + + VendorAtom event = {.reverseDomainName = PixelAtoms::ReverseDomainNames().pixel(), + .atomId = PixelAtoms::Ids::DEVICE_ORIENTATION, + .values = values}; + Return<void> retOrientation = stats_client->reportVendorAtom(event); + if (!retOrientation.isOk()) + ALOGE("Unable to report Orientation to Stats service"); + orientationCollector->disableOrientationSensor(); + } +} + +bool WlcReporter::isWlcSupported() { + std::string file_contents; + + if (!ReadFileToString(POWER_SUPPLY_SYSFS_PATH, &file_contents)) { + ALOGV("Unable to read %s - %s", POWER_SUPPLY_SYSFS_PATH, strerror(errno)); + return false; + } else { + return true; + } +} + +bool WlcReporter::isWlcOnline() { + std::string file_contents; + + if (!ReadFileToString(POWER_SUPPLY_SYSFS_PATH, &file_contents)) { + ALOGE("Unable to read %s - %s", POWER_SUPPLY_SYSFS_PATH, strerror(errno)); + return false; + } + ALOGV("isWlcOnline value: %s", file_contents.c_str()); + return file_contents == "1\n"; +} + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android diff --git a/pixelstats/include/pixelstats/OrientationCollector.h b/pixelstats/include/pixelstats/OrientationCollector.h new file mode 100644 index 00000000..e3ca6416 --- /dev/null +++ b/pixelstats/include/pixelstats/OrientationCollector.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 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 <android/hidl/base/1.0/IBase.h> +#include <android/sensor.h> + +#ifndef HARDWARE_GOOGLE_PIXEL_ORIENTATION_COLLECTOR_H +#define HARDWARE_GOOGLE_PIXEL_ORIENTATION_COLLECTOR_H + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +/** + * A class to help use Senser + */ +class OrientationCollector : public RefBase { + public: + static sp<OrientationCollector> createOrientationCollector(); + + int32_t pollOrientation(int *orientation); + int32_t init(); + void disableOrientationSensor(); + + private: + ASensorEventQueue *mQueue; + ASensorManager *mSensorManager = nullptr; + ASensorRef mOrientationSensor; + + int getEvents(ASensorEvent *event_list, size_t event_list_size, int *event_count); +}; + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android + +#endif // HARDWARE_GOOGLE_PIXEL_ORIENTATION_COLLECTOR_H diff --git a/pixelstats/include/pixelstats/UeventListener.h b/pixelstats/include/pixelstats/UeventListener.h index e7a68b49..0f4538f7 100644 --- a/pixelstats/include/pixelstats/UeventListener.h +++ b/pixelstats/include/pixelstats/UeventListener.h @@ -54,6 +54,7 @@ class UeventListener { void ReportChargeStats(const sp<IStats> &stats_client, const char *line); void ReportVoltageTierStats(const sp<IStats> &stats_client, const char *line); void ReportChargeMetricsEvent(const char *driver); + void ReportWlc(const char *driver); const std::string kAudioUevent; const std::string kUsbPortOverheatPath; @@ -64,6 +65,9 @@ class UeventListener { const int kVendorAtomOffset = 2; int uevent_fd_; + + bool mIsWirelessChargingLastState; + bool mIsWirelessChargingSupported; }; } // namespace pixel diff --git a/pixelstats/include/pixelstats/WlcReporter.h b/pixelstats/include/pixelstats/WlcReporter.h new file mode 100644 index 00000000..d29b7b4e --- /dev/null +++ b/pixelstats/include/pixelstats/WlcReporter.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 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. + */ + +#ifndef HARDWARE_GOOGLE_PIXEL_PIXELSTATS_WLCREPORTER_H +#define HARDWARE_GOOGLE_PIXEL_PIXELSTATS_WLCREPORTER_H + +#include <android/frameworks/stats/1.0/IStats.h> +#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h> + +using android::frameworks::stats::V1_0::IStats; + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +/** + * A class to upload wireless metrics + */ +class WlcReporter : public RefBase { + public: + /* checkAndReport + * isWirelessChargingLast: last wireless charge state + * true, for wireless charging + * Return: current wireless charge state + */ + bool checkAndReport(bool isWirelessChargingLast); + bool isWlcSupported(); + + private: + bool isWlcOnline(); + bool readFileToInt(const char *path, int *val); + + void doLog(); + // Translate device orientation value from sensor Hal to atom enum value + int translateDeviceOrientationToAtomValue(int orientation); + + // Proto messages are 1-indexed and VendorAtom field numbers start at 2, so + // store everything in the values array at the index of the field number + // -2. + const int kVendorAtomOffset = 2; + int readPtmcId(); +}; + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android + +#endif // HARDWARE_GOOGLE_PIXEL_PIXELSTATS_WLCREPORTER_H |