Usb: capture and upload Suez metric VendorUsbDataSessionEvent
Upload metrics for the last data session that just ends upon data role changes. The change is purely metric collection and does not change any business logic. This is a direct CP from ag/24816727 Bug: 297224564 Test: Trigger metric upload for both host and device mode and verify it by statsd_testdrive Change-Id: I823ae8712b7914cfc7f6c6379acb3749d13c0974 (cherry picked from commit ccb35c81ff0bbfb013136bae7a572280b196bd1a)
This commit is contained in:
parent
2685ea8e57
commit
653f31663d
3 changed files with 101 additions and 5 deletions
|
@ -49,7 +49,7 @@ cc_binary {
|
|||
"android.frameworks.stats-V2-ndk",
|
||||
"pixelatoms-cpp",
|
||||
"libbinder_ndk",
|
||||
|
||||
"libprotobuf-cpp-lite",
|
||||
],
|
||||
static_libs: [
|
||||
"libpixelusb",
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "Usb.h"
|
||||
|
||||
#include <aidl/android/frameworks/stats/IStats.h>
|
||||
#include <pixelusb/CommonUtils.h>
|
||||
#include <pixelusb/UsbGadgetCommon.h>
|
||||
#include <pixelstats/StatsHelper.h>
|
||||
|
||||
|
@ -49,6 +50,9 @@ using android::base::Trim;
|
|||
using android::hardware::google::pixel::getStatsService;
|
||||
using android::hardware::google::pixel::PixelAtoms::VendorUsbPortOverheat;
|
||||
using android::hardware::google::pixel::reportUsbPortOverheat;
|
||||
using android::hardware::google::pixel::PixelAtoms::VendorUsbDataSessionEvent;
|
||||
using android::hardware::google::pixel::reportUsbDataSessionEvent;
|
||||
using android::hardware::google::pixel::usb::BuildVendorUsbDataSessionEvent;
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
|
@ -88,6 +92,8 @@ constexpr char kHostUeventRegex[] = "^(bind|unbind)@(/devices/platform/11110000\
|
|||
constexpr int kSamplingIntervalSec = 5;
|
||||
void queryVersionHelper(android::hardware::usb::Usb *usb,
|
||||
std::vector<PortStatus> *currentPortStatus);
|
||||
void queryUsbDataSession(android::hardware::usb::Usb *usb,
|
||||
std::vector<PortStatus> *currentPortStatus);
|
||||
|
||||
#define USB_STATE_MAX_LEN 20
|
||||
|
||||
|
@ -895,6 +901,7 @@ void queryVersionHelper(android::hardware::usb::Usb *usb,
|
|||
queryMoistureDetectionStatus(usb, currentPortStatus);
|
||||
queryPowerTransferStatus(usb, currentPortStatus);
|
||||
queryNonCompliantChargerStatus(currentPortStatus);
|
||||
queryUsbDataSession(usb, currentPortStatus);
|
||||
if (usb->mCallback != NULL) {
|
||||
ScopedAStatus ret = usb->mCallback->notifyPortStatusChange(*currentPortStatus,
|
||||
status);
|
||||
|
@ -981,6 +988,54 @@ void report_overheat_event(android::hardware::usb::Usb *usb) {
|
|||
}
|
||||
}
|
||||
|
||||
void report_usb_data_session_event(android::hardware::usb::Usb *usb) {
|
||||
std::vector<VendorUsbDataSessionEvent> events;
|
||||
|
||||
if (usb->mDataRole == PortDataRole::DEVICE) {
|
||||
VendorUsbDataSessionEvent event;
|
||||
BuildVendorUsbDataSessionEvent(false /* is_host */, std::chrono::steady_clock::now(),
|
||||
usb->mDataSessionStart, &usb->mDeviceState.states,
|
||||
&usb->mDeviceState.timestamps, &event);
|
||||
events.push_back(event);
|
||||
} else if (usb->mDataRole == PortDataRole::HOST) {
|
||||
bool empty = true;
|
||||
for (auto &entry : usb->mHostStateMap) {
|
||||
// Host port will at least get an not_attached event after enablement,
|
||||
// skip upload if no additional state is added.
|
||||
if (entry.second.states.size() > 1) {
|
||||
VendorUsbDataSessionEvent event;
|
||||
BuildVendorUsbDataSessionEvent(true /* is_host */, std::chrono::steady_clock::now(),
|
||||
usb->mDataSessionStart, &entry.second.states,
|
||||
&entry.second.timestamps, &event);
|
||||
events.push_back(event);
|
||||
empty = false;
|
||||
}
|
||||
}
|
||||
// All host ports have no state update, upload an event to reflect it
|
||||
if (empty && usb->mHostStateMap.size() > 0) {
|
||||
VendorUsbDataSessionEvent event;
|
||||
BuildVendorUsbDataSessionEvent(true /* is_host */, std::chrono::steady_clock::now(),
|
||||
usb->mDataSessionStart,
|
||||
&usb->mHostStateMap.begin()->second.states,
|
||||
&usb->mHostStateMap.begin()->second.timestamps,
|
||||
&event);
|
||||
events.push_back(event);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
const shared_ptr<IStats> stats_client = getStatsService();
|
||||
if (!stats_client) {
|
||||
ALOGE("Unable to get AIDL Stats service");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &event : events) {
|
||||
reportUsbDataSessionEvent(stats_client, event);
|
||||
}
|
||||
}
|
||||
|
||||
static void unregisterEpollEntry(Usb *usb, std::string name) {
|
||||
std::map<std::string, struct Usb::epollEntry> *map;
|
||||
int fd;
|
||||
|
@ -1054,14 +1109,16 @@ static int registerEpollEntryByFile(Usb *usb, std::string name, int flags,
|
|||
}
|
||||
|
||||
static void clearUsbDeviceState(struct Usb::usbDeviceState *device) {
|
||||
device->latestState.clear();
|
||||
device->states.clear();
|
||||
device->timestamps.clear();
|
||||
device->portResetCount = 0;
|
||||
}
|
||||
|
||||
static void updateUsbDeviceState(struct Usb::usbDeviceState *device, char *state) {
|
||||
ALOGI("Update USB device state: %s", state);
|
||||
|
||||
device->latestState = state;
|
||||
device->states.push_back(state);
|
||||
device->timestamps.push_back(std::chrono::steady_clock::now());
|
||||
|
||||
if (!std::strcmp(state, "configured\n")) {
|
||||
device->portResetCount = 0;
|
||||
|
@ -1081,6 +1138,37 @@ static void host_event(uint32_t /*epevents*/, struct Usb::payload *payload) {
|
|||
updateUsbDeviceState(&payload->usb->mHostStateMap[payload->name], state);
|
||||
}
|
||||
|
||||
void queryUsbDataSession(android::hardware::usb::Usb *usb,
|
||||
std::vector<PortStatus> *currentPortStatus) {
|
||||
PortDataRole newDataRole = (*currentPortStatus)[0].currentDataRole;
|
||||
PowerBrickStatus newPowerBrickStatus = (*currentPortStatus)[0].powerBrickStatus;
|
||||
|
||||
if (newDataRole != usb->mDataRole) {
|
||||
// Upload metrics for the last non-powerbrick data session that has ended
|
||||
if (usb->mDataRole != PortDataRole::NONE && !usb->mIsPowerBrickConnected) {
|
||||
report_usb_data_session_event(usb);
|
||||
}
|
||||
|
||||
// Set up for the new data session
|
||||
usb->mDataRole = newDataRole;
|
||||
usb->mDataSessionStart = std::chrono::steady_clock::now();
|
||||
usb->mIsPowerBrickConnected = (newPowerBrickStatus == PowerBrickStatus::CONNECTED);
|
||||
if (newDataRole == PortDataRole::DEVICE) {
|
||||
clearUsbDeviceState(&usb->mDeviceState);
|
||||
} else if (newDataRole == PortDataRole::HOST) {
|
||||
for (auto &entry : usb->mHostStateMap) {
|
||||
clearUsbDeviceState(&entry.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PowerBrickStatus could flip from DISCONNECTED to CONNECTED during the same data
|
||||
// session when BC1.2 SDP times out and falls back to DCP
|
||||
if (newPowerBrickStatus == PowerBrickStatus::CONNECTED) {
|
||||
usb->mIsPowerBrickConnected = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void uevent_event(uint32_t /*epevents*/, struct Usb::payload *payload) {
|
||||
char msg[UEVENT_MSG_LEN + 2];
|
||||
char *cp;
|
||||
|
@ -1153,7 +1241,6 @@ static void uevent_event(uint32_t /*epevents*/, struct Usb::payload *payload) {
|
|||
registerEpollEntryByFile(payload->usb, path, EPOLLPRI, host_event);
|
||||
} else if (action == "unbind") {
|
||||
unregisterEpollEntry(payload->usb, path);
|
||||
clearUsbDeviceState(&payload->usb->mHostStateMap[path]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <android-base/file.h>
|
||||
#include <aidl/android/hardware/usb/BnUsb.h>
|
||||
#include <aidl/android/hardware/usb/BnUsbCallback.h>
|
||||
#include <chrono>
|
||||
#include <pixelusb/UsbOverheatEvent.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
|
@ -92,12 +93,20 @@ struct Usb : public BnUsb {
|
|||
|
||||
// USB device state monitoring
|
||||
struct usbDeviceState {
|
||||
std::string latestState;
|
||||
// Usb device state raw strings read from sysfs
|
||||
std::vector<std::string> states;
|
||||
// Timestamps of when the usb device states were captured
|
||||
std::vector<std::chrono::steady_clock::time_point> timestamps;
|
||||
int portResetCount;
|
||||
};
|
||||
struct usbDeviceState mDeviceState;
|
||||
// Map host device path name to usbDeviceState
|
||||
std::map<std::string, struct usbDeviceState> mHostStateMap;
|
||||
// Cache relevant info for USB data session metrics collection when a session starts, including
|
||||
// the data role, power brick status and the time when the session starts.
|
||||
PortDataRole mDataRole;
|
||||
bool mIsPowerBrickConnected;
|
||||
std::chrono::steady_clock::time_point mDataSessionStart;
|
||||
|
||||
// File monitoring through epoll
|
||||
int mEpollFd;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue