summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenny cy Lee <dennycylee@google.com>2020-01-10 09:36:06 +0800
committerDenny cy Lee <dennycylee@google.com>2020-04-08 02:20:37 +0000
commita2653edce83c92635ec264cd28b3492259244458 (patch)
treecf39bb22a2da36c28bfcdb155d479214ea22477e
parent766a32af23ace6ffe9e9cc60c1adc9bc59c1e469 (diff)
downloadpixel-a2653edce83c92635ec264cd28b3492259244458.tar.gz
Pixelstats: Add 2 wireless charging metrics
Upload metrics, "device orientation" and "1P/3P charger", when wireless charging starts. Bug: 141605895 Test: Manually, adb shell cmd stats print-logs;adb logcat |egrep "statsd.*\(10500. \)0x10000->" Change-Id: I7486cc6ea9ca50e63cc5bfe9c58bdd592020f5b4
-rw-r--r--pixelstats/Android.bp3
-rw-r--r--pixelstats/OrientationCollector.cpp140
-rw-r--r--pixelstats/UeventListener.cpp35
-rw-r--r--pixelstats/WlcReporter.cpp152
-rw-r--r--pixelstats/include/pixelstats/OrientationCollector.h52
-rw-r--r--pixelstats/include/pixelstats/UeventListener.h4
-rw-r--r--pixelstats/include/pixelstats/WlcReporter.h63
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