func printResults(outputProto *bspb.BatteryStats, fileName string, dir string) { if outputProto == nil { fmt.Println("Inputs were identical.") return } fmt.Printf("\n################\n") fmt.Printf("Partial Wakelocks\n") fmt.Printf("################\n\n") var pwl []*checkinparse.WakelockInfo for _, app := range outputProto.App { for _, pw := range app.Wakelock { pwl = append(pwl, &checkinparse.WakelockInfo{ Name: fmt.Sprintf("%s : %s", app.GetName(), pw.GetName()), UID: app.GetUid(), Duration: time.Duration(pw.GetPartialTimeMsec()) * time.Millisecond, }) } } checkinparse.SortByAbsTime(pwl) for _, pw := range pwl[:min(10, len(pwl))] { fmt.Printf("%s (File1 uid=%d) %s\n", pw.Duration, pw.UID, pw.Name) } fmt.Printf("\n################\n") fmt.Printf("Kernel Wakelocks\n") fmt.Printf("################\n\n") var kwl []*checkinparse.WakelockInfo for _, kw := range outputProto.GetSystem().KernelWakelock { if kw.GetName() != "PowerManagerService.WakeLocks" { kwl = append(kwl, &checkinparse.WakelockInfo{ Name: kw.GetName(), Duration: time.Duration(kw.GetTimeMsec()) * time.Millisecond, }) } } checkinparse.SortByAbsTime(kwl) for _, kw := range kwl[:min(10, len(kwl))] { fmt.Printf("%s %s\n", kw.Duration, kw.Name) } data, err := proto.Marshal(outputProto) if err != nil { log.Fatalf("Cannot marshal output proto: %v", err) } ioutil.WriteFile(fileName+".proto", data, 0600) ioutil.WriteFile(dir+"/"+fileName+".proto", data, 0600) }
func parseAppStats(checkin *bspb.BatteryStats) []*bspb.BatteryStats_App { var as []*bspb.BatteryStats_App unknown := 1 for _, a := range checkin.GetApp() { if a.GetName() == "" { a.Name = proto.String("UNKNOWN_" + strconv.Itoa(unknown)) unknown++ } as = append(as, a) } // Sort by name so that we can display the apps in alphabetical order in the dropdown. sort.Sort(byName(as)) return as }
func parseAppStats(checkin *bspb.BatteryStats, sensors map[int32]bugreportutils.SensorInfo) []AppStat { var as []AppStat bCapMah := checkin.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() for _, app := range checkin.GetApp() { a := AppStat{ DevicePowerPrediction: 100 * float32(app.GetPowerUseItem().GetComputedPowerMah()) / bCapMah, RawStats: app, } if app.GetName() == "" { app.Name = proto.String(fmt.Sprintf("UNKNOWN_%d", app.GetUid())) } // Only add it to AppStat if the CPU field exists and is therefore populated. if app.Cpu != nil { a.CPUPowerPrediction = 100 * (app.Cpu.GetPowerMaMs() / (1000 * 60 * 60)) / bCapMah } for _, u := range app.GetUserActivity() { a.UserActivity = append(a.UserActivity, userActivity{ Type: u.GetName().String(), Count: u.GetCount(), }) } for _, s := range app.GetSensor() { sensor, ok := sensors[s.GetNumber()] if !ok { sensor = bugreportutils.SensorInfo{ Name: fmt.Sprintf("unknown sensor (#%d)", s.GetNumber()), Number: s.GetNumber(), } } sensor.TotalTimeMs = int64(s.GetTotalTimeMsec()) sensor.Count = s.GetCount() a.Sensor = append(a.Sensor, sensor) } as = append(as, a) } // Sort by name so that we can display the apps in alphabetical order in the dropdown. sort.Sort(byName(as)) return as }
// ParseCheckinData creates a Checkin struct from the given aggregated battery stats. func ParseCheckinData(c *bspb.BatteryStats) Checkin { if c == nil { return Checkin{} } realtime := time.Duration(c.System.Battery.GetBatteryRealtimeMsec()) * time.Millisecond out := Checkin{ Device: c.Build.GetDevice(), Build: c.Build.GetBuildId(), BuildFingerprint: c.Build.GetFingerprint(), ReportVersion: c.GetReportVersion(), Realtime: realtime, ScreenOffRealtime: time.Duration(c.System.Battery.GetScreenOffRealtimeMsec()) * time.Millisecond, ScreenOffDischargePoints: c.System.BatteryDischarge.GetScreenOff(), ScreenOnDischargePoints: c.System.BatteryDischarge.GetScreenOn(), EstimatedDischarge: c.System.PowerUseSummary.GetComputedPowerMah(), ActualDischarge: (c.System.PowerUseSummary.GetMinDrainedPowerMah() + c.System.PowerUseSummary.GetMaxDrainedPowerMah()) / 2, // Uptime is the same as screen-off uptime + screen on time Uptime: MDuration{ V: (time.Duration(c.System.Battery.GetBatteryUptimeMsec()) * time.Millisecond), }, ScreenOffUptime: MDuration{ V: (time.Duration(c.System.Battery.GetScreenOffUptimeMsec()) * time.Millisecond), }, ScreenOnTime: MDuration{ V: (time.Duration(c.System.Misc.GetScreenOnTimeMsec()) * time.Millisecond), }, PartialWakelockTime: MDuration{ V: (time.Duration(c.System.Misc.GetPartialWakelockTimeMsec()) * time.Millisecond), }, KernelOverheadTime: MDuration{ V: (time.Duration(c.System.Battery.GetScreenOffUptimeMsec()-c.System.Misc.GetPartialWakelockTimeMsec()) * time.Millisecond), }, SignalScanningTime: MDuration{ V: (time.Duration(c.System.SignalScanningTime.GetTimeMsec()) * time.Millisecond), }, MobileActiveTime: MDuration{ V: (time.Duration(c.System.Misc.GetMobileActiveTimeMsec()) * time.Millisecond), }, PhoneCallTime: MDuration{ V: (time.Duration(c.System.Misc.GetPhoneOnTimeMsec()) * time.Millisecond), }, WifiOnTime: MDuration{ V: (time.Duration(c.System.Misc.GetWifiOnTimeMsec()) * time.Millisecond), }, DeviceIdleModeEnabledTime: MDuration{ V: (time.Duration(c.System.Misc.GetDeviceIdleModeEnabledTimeMsec()) * time.Millisecond), }, DeviceIdlingTime: MDuration{ V: (time.Duration(c.System.Misc.GetDeviceIdlingTimeMsec()) * time.Millisecond), }, FullWakelockTime: MDuration{ V: (time.Duration(c.System.Misc.GetFullWakelockTimeMsec()) * time.Millisecond), }, InteractiveTime: MDuration{ V: (time.Duration(c.System.Misc.GetInteractiveTimeMsec()) * time.Millisecond), }, BluetoothOnTime: MDuration{ V: (time.Duration(c.System.Misc.GetBluetoothOnTimeMsec()) * time.Millisecond), }, LowPowerModeEnabledTime: MDuration{ V: (time.Duration(c.System.Misc.GetLowPowerModeEnabledTimeMsec()) * time.Millisecond), }, ConnectivityChanges: c.System.Misc.GetConnectivityChanges(), } out.ScreenOffUptimePercentage = (float32(out.ScreenOffUptime.V) / float32(realtime)) * 100 out.ScreenOnTimePercentage = (float32(out.ScreenOnTime.V) / float32(realtime)) * 100 out.PartialWakelockTimePercentage = (float32(out.PartialWakelockTime.V) / float32(realtime)) * 100 out.KernelOverheadTimePercentage = (float32(out.KernelOverheadTime.V) / float32(realtime)) * 100 out.SignalScanningTimePercentage = (float32(out.SignalScanningTime.V) / float32(realtime)) * 100 out.MobileActiveTimePercentage = (float32(out.MobileActiveTime.V) / float32(realtime)) * 100 out.FullWakelockTimePercentage = (float32(out.FullWakelockTime.V) / float32(realtime)) * 100 out.PhoneCallTimePercentage = (float32(out.PhoneCallTime.V) / float32(realtime)) * 100 out.DeviceIdleModeEnabledTimePercentage = (float32(out.DeviceIdleModeEnabledTime.V) / float32(realtime)) * 100 out.DeviceIdlingTimePercentage = (float32(out.DeviceIdlingTime.V) / float32(realtime)) * 100 out.InteractiveTimePercentage = (float32(out.InteractiveTime.V) / float32(realtime)) * 100 out.BluetoothOnTimePercentage = (float32(out.BluetoothOnTime.V) / float32(realtime)) * 100 out.LowPowerModeEnabledTimePercentage = (float32(out.LowPowerModeEnabledTime.V) / float32(realtime)) * 100 out.MobileKiloBytesPerHr = MFloat32{V: (c.System.GlobalNetwork.GetMobileBytesRx() + c.System.GlobalNetwork.GetMobileBytesTx()) / (1024 * float32(realtime.Hours()))} out.WifiKiloBytesPerHr = MFloat32{V: (c.System.GlobalNetwork.GetWifiBytesRx() + c.System.GlobalNetwork.GetWifiBytesTx()) / (1024 * float32(realtime.Hours()))} if c.GetReportVersion() >= 14 { out.WifiOnTime = MDuration{V: time.Duration(c.System.GlobalWifi.GetWifiOnTimeMsec()) * time.Millisecond} out.WifiOnTimePercentage = (float32(out.WifiOnTime.V) / float32(realtime)) * 100 out.WifiIdleTime = MDuration{V: time.Duration(c.System.GlobalWifi.GetWifiIdleTimeMsec()) * time.Millisecond} out.WifiTransmitTime = MDuration{V: time.Duration(c.System.GlobalWifi.GetWifiRxTimeMsec()+c.System.GlobalWifi.GetWifiTxTimeMsec()) * time.Millisecond} out.WifiTransmitTimePercentage = (float32(out.WifiTransmitTime.V) / float32(realtime)) * 100 out.WifiDischargePoints = 100 * c.System.GlobalWifi.GetWifiPowerMah() / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() out.WifiDischargeRatePerHr = MFloat32{ V: 100 * c.System.GlobalWifi.GetWifiPowerMah() / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() / float32(realtime.Hours()), } out.BluetoothIdleTime = MDuration{V: time.Duration(c.System.GlobalBluetooth.GetBluetoothIdleTimeMsec()) * time.Millisecond} out.BluetoothTransmitTime = MDuration{V: time.Duration(c.System.GlobalBluetooth.GetBluetoothRxTimeMsec()+c.System.GlobalBluetooth.GetBluetoothTxTimeMsec()) * time.Millisecond} out.BluetoothTransmitTimePercentage = (float32(out.BluetoothTransmitTime.V) / float32(realtime)) * 100 out.BluetoothDischargePoints = 100 * c.System.GlobalBluetooth.GetBluetoothPowerMah() / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() out.BluetoothDischargeRatePerHr = MFloat32{ V: 100 * c.System.GlobalBluetooth.GetBluetoothPowerMah() / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() / float32(realtime.Hours()), } } if s := c.System.Battery.GetScreenOffRealtimeMsec(); s > 0 { out.ScreenOffDischargeRatePerHr = MFloat32{V: 60 * 60 * 1000 * c.System.BatteryDischarge.GetScreenOff() / s} } if s := c.System.Misc.GetScreenOnTimeMsec(); s > 0 { out.ScreenOnDischargeRatePerHr = MFloat32{V: 60 * 60 * 1000 * c.System.BatteryDischarge.GetScreenOn() / s} } // Screen Brightness. out.ScreenBrightness = make(map[string]float32) for _, sb := range c.System.ScreenBrightness { out.ScreenBrightness[sb.GetName().String()] += (sb.GetTimeMsec() / msecsInMinute) / float32(realtime.Hours()) } // Signal Strength. out.SignalStrength = make(map[string]float32) for _, ss := range c.System.SignalStrength { out.SignalStrength[ss.GetName().String()] += (ss.GetTimeMsec() / msecsInMinute) / float32(realtime.Hours()) } // Wifi Signal Strength. out.WifiSignalStrength = make(map[string]float32) for _, ws := range c.System.WifiSignalStrength { out.WifiSignalStrength[ws.GetName().String()] += (ws.GetTimeMsec() / msecsInMinute) / float32(realtime.Hours()) } // Bluetooth States. out.BluetoothState = make(map[string]float32) for _, bs := range c.System.BluetoothState { out.BluetoothState[bs.GetName().String()] += (bs.GetTimeMsec() / msecsInMinute) / float32(realtime.Hours()) } // DataConnection out.DataConnection = make(map[string]float32) for _, dc := range c.System.DataConnection { out.DataConnection[dc.GetName().String()] += (dc.GetTimeMsec() / msecsInMinute) / float32(realtime.Hours()) } // Kernel Wakelocks. var kwl []*checkinparse.WakelockInfo for _, kw := range c.System.KernelWakelock { if kw.GetName() != "PowerManagerService.WakeLocks" && kw.GetTimeMsec() >= 0.01 { kwl = append(kwl, &checkinparse.WakelockInfo{ Name: kw.GetName(), Duration: time.Duration(kw.GetTimeMsec()) * time.Millisecond, Count: kw.GetCount(), }) } } // Sorting Kernel Wakelocks by time. checkinparse.SortByTime(kwl) for _, kw := range kwl { out.KernelWakelocks = append(out.KernelWakelocks, ActivityData{ Name: kw.Name, Count: kw.Count, CountPerHour: kw.Count / float32(realtime.Hours()), Duration: kw.Duration, SecondsPerHr: float32(kw.Duration.Seconds()) / float32(realtime.Hours()), }) } // Wakeup Reasons. var wrl []*checkinparse.WakelockInfo for _, wr := range c.System.WakeupReason { if wr.GetTimeMsec() >= 0.01 { wrl = append(wrl, &checkinparse.WakelockInfo{ Name: wr.GetName(), Duration: time.Duration(wr.GetTimeMsec()) * time.Millisecond, Count: wr.GetCount(), }) } } // Sorting Wakeup Reasons by count. checkinparse.SortByCount(wrl) for _, wr := range wrl { out.WakeupReasons = append(out.WakeupReasons, ActivityData{ Name: wr.Name, Count: wr.Count, CountPerHour: wr.Count / float32(realtime.Hours()), Duration: wr.Duration, SecondsPerHr: float32(wr.Duration.Seconds()) / float32(realtime.Hours()), }) } // Power usage per app. var e []*PowerUseData // Network usage per app. var m []*checkinparse.WakelockInfo var n []*NetworkTrafficData // App wakeup count. var wu []*RateData // App ANR and crash count. var ac []*ANRCrashData // CPU use per app. var cpu []*CPUData // Wifi activity per app. var wfScan []*checkinparse.WakelockInfo var wfFull []*checkinparse.WakelockInfo // SyncManager Tasks. var stl []*checkinparse.WakelockInfo // Userspace Partial Wakelocks and GPS use. var pwl []*checkinparse.WakelockInfo var gps []*checkinparse.WakelockInfo // Camera use per app. var ca []*checkinparse.WakelockInfo // Flashlight use per app. var fla []*checkinparse.WakelockInfo au := make(map[string]int32) bCapMah := c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() for _, app := range c.App { if app.GetName() == "" { app.Name = proto.String(fmt.Sprintf("UNKNOWN_%d", app.GetUid())) } au[app.GetName()] = app.GetUid() this := AppData{ Name: app.GetName(), UID: app.GetUid(), } if pct := 100 * app.PowerUseItem.GetComputedPowerMah() / bCapMah; pct >= 0.01 { e = append(e, &PowerUseData{ Name: app.GetName(), UID: app.GetUid(), Percent: pct, }) } if mat, mac := app.Network.GetMobileActiveTimeMsec(), app.Network.GetMobileActiveCount(); mat >= 0.01 || mac > 0 { m = append(m, &checkinparse.WakelockInfo{ Name: app.GetName(), UID: app.GetUid(), Duration: time.Duration(mat) * time.Millisecond, Count: mac, }) } wr := app.Network.GetWifiBytesRx() wt := app.Network.GetWifiBytesTx() mt := app.Network.GetMobileBytesTx() mr := app.Network.GetMobileBytesRx() if wr+wt+mt+mr >= 0.01 { ntd := NetworkTrafficData{ Name: app.GetName(), UID: app.GetUid(), WifiMegaBytes: (wr + wt) / (1024 * 1024), MobileMegaBytes: (mr + mt) / (1024 * 1024), WifiMegaBytesPerHour: (wr + wt) / (1024 * 1024) / float32(realtime.Hours()), MobileMegaBytesPerHour: (mr + mt) / (1024 * 1024) / float32(realtime.Hours()), } n = append(n, &ntd) this.Network = ntd } if w := app.Apk.GetWakeups(); w > 0 { rd := RateData{ Name: app.GetName(), UID: app.GetUid(), Count: w, CountPerHr: w / float32(realtime.Hours()), } wu = append(wu, &rd) this.Alarms = rd } for _, p := range app.Process { if an, cr := p.GetAnrs(), p.GetCrashes(); an > 0 || cr > 0 { ac = append(ac, &ANRCrashData{ Name: fmt.Sprintf("%s : %s", app.GetName(), p.GetName()), UID: app.GetUid(), ANRCount: int32(an), CrashCount: int32(cr), }) out.TotalAppANRCount += int32(an) out.TotalAppCrashCount += int32(cr) } } out.TotalAppANRRate = float32(out.TotalAppANRCount) / float32(realtime.Hours()) out.TotalAppCrashRate = float32(out.TotalAppCrashCount) / float32(realtime.Hours()) if ut, st := app.Cpu.GetUserTimeMs(), app.Cpu.GetSystemTimeMs(); ut > 0 || st > 0 { cpud := CPUData{ Name: app.GetName(), UID: app.GetUid(), UserTime: time.Duration(ut) * time.Millisecond, SystemTime: time.Duration(st) * time.Millisecond, PowerPct: 100 * (app.Cpu.GetPowerMaMs() / (1000 * 60 * 60)) / bCapMah, } cpu = append(cpu, &cpud) this.CPU = cpud } if wfl := app.Wifi.GetFullWifiLockTimeMsec(); wfl > 0 { wfFull = append(wfFull, &checkinparse.WakelockInfo{ Name: app.GetName(), UID: app.GetUid(), Duration: time.Duration(wfl) * time.Millisecond, }) } wst := app.Wifi.GetScanTimeMsec() wsc := app.Wifi.GetScanCount() if wst > 0 || wsc > 0 { wfScan = append(wfScan, &checkinparse.WakelockInfo{ Name: app.GetName(), UID: app.GetUid(), Duration: time.Duration(wst) * time.Millisecond, Count: wsc, }) this.WifiScan = ActivityData{ Name: app.GetName(), UID: app.GetUid(), Count: wsc, CountPerHour: wsc / float32(realtime.Hours()), Duration: time.Duration(wst) * time.Millisecond, SecondsPerHr: float32(time.Duration(wst).Seconds()) / float32(realtime.Hours()), } } var stlt []*checkinparse.WakelockInfo for _, st := range app.Sync { stlt = append(stlt, &checkinparse.WakelockInfo{ Name: fmt.Sprintf("%s : %s", app.GetName(), st.GetName()), UID: app.GetUid(), Duration: time.Duration(st.GetTotalTimeMsec()) * time.Millisecond, Count: st.GetCount(), }) } stl = append(stl, stlt...) this.Syncs = sumWakelockInfo(stlt, realtime) this.Syncs.Name = app.GetName() this.Syncs.UID = app.GetUid() var pwlt []*checkinparse.WakelockInfo for _, pw := range app.Wakelock { pwlt = append(pwlt, &checkinparse.WakelockInfo{ Name: fmt.Sprintf("%s : %s", app.GetName(), pw.GetName()), UID: app.GetUid(), Duration: time.Duration(pw.GetPartialTimeMsec()) * time.Millisecond, Count: pw.GetPartialCount(), }) } pwl = append(pwl, pwlt...) this.PartialWakelocks = sumWakelockInfo(pwlt, realtime) this.PartialWakelocks.Name = app.GetName() this.PartialWakelocks.UID = app.GetUid() var gpst []*checkinparse.WakelockInfo for _, s := range app.Sensor { if s.GetNumber() == bugreportutils.GPSSensorNumber { gpst = append(gpst, &checkinparse.WakelockInfo{ Name: app.GetName(), UID: app.GetUid(), Duration: time.Duration(s.GetTotalTimeMsec()) * time.Millisecond, Count: s.GetCount(), }) continue } } gps = append(gps, gpst...) this.GPSUse = sumWakelockInfo(gpst, realtime) this.GPSUse.Name = app.GetName() this.GPSUse.UID = app.GetUid() if cat, cac := app.Camera.GetTotalTimeMsec(), app.Camera.GetCount(); cat > 0 || cac > 0 { ca = append(ca, &checkinparse.WakelockInfo{ Name: app.GetName(), UID: app.GetUid(), Duration: time.Duration(cat) * time.Millisecond, Count: cac, }) } if flt, flc := app.Flashlight.GetTotalTimeMsec(), app.Flashlight.GetCount(); flt > 0 || flc > 0 { fla = append(fla, &checkinparse.WakelockInfo{ Name: app.GetName(), UID: app.GetUid(), Duration: time.Duration(flt) * time.Millisecond, Count: flc, }) } out.AggregatedApps = append(out.AggregatedApps, this) } for _, pwi := range c.System.PowerUseItem { if pwi.GetName() == bspb.BatteryStats_System_PowerUseItem_APP { // We have the apps split up in the preceding for loop, and the APP entry is just the sum of all of them, so we skip it here. continue } if pct := 100 * pwi.GetComputedPowerMah() / bCapMah; pct >= 0.01 { e = append(e, &PowerUseData{ Name: pwi.GetName().String(), Percent: pct, }) } } sort.Sort(byPercent(e)) for _, ent := range e { out.DevicePowerEstimates = append(out.DevicePowerEstimates, *ent) } checkinparse.SortByTime(m) for _, mad := range m { out.TopMobileActiveApps = append(out.TopMobileActiveApps, ActivityData{ Name: mad.Name, UID: mad.UID, Count: mad.Count, CountPerHour: mad.Count / float32(realtime.Hours()), Duration: mad.Duration, SecondsPerHr: float32(mad.Duration.Seconds()) / float32(realtime.Hours()), }) } sort.Sort(byMobileBytes(n)) for _, ntd := range n { if ntd.MobileMegaBytes >= 0.01 { out.TopMobileTrafficApps = append(out.TopMobileTrafficApps, *ntd) } } sort.Sort(byWifiBytes(n)) for _, ntd := range n { if ntd.WifiMegaBytes >= 0.01 { out.TopWifiTrafficApps = append(out.TopWifiTrafficApps, *ntd) } } sort.Sort(byCount(wu)) for _, w := range wu { out.AppWakeups = append(out.AppWakeups, *w) out.TotalAppWakeupsPerHr += w.CountPerHr } sort.Sort(byCrashThenANR(ac)) for _, x := range ac { out.ANRAndCrash = append(out.ANRAndCrash, *x) } sort.Sort(byPower(cpu)) for _, cp := range cpu { out.CPUUsage = append(out.CPUUsage, *cp) out.TotalAppCPUPowerPct += cp.PowerPct } checkinparse.SortByTime(wfScan) for _, w := range wfScan { out.WifiScanActivity = append(out.WifiScanActivity, ActivityData{ Name: w.Name, UID: w.UID, Count: w.Count, CountPerHour: w.Count / float32(realtime.Hours()), Duration: w.Duration, SecondsPerHr: float32(w.Duration.Seconds()) / float32(realtime.Hours()), }) } checkinparse.SortByTime(wfFull) for _, w := range wfFull { out.WifiFullLockActivity = append(out.WifiFullLockActivity, ActivityData{ Name: w.Name, UID: w.UID, Duration: w.Duration, SecondsPerHr: float32(w.Duration.Seconds()) / float32(realtime.Hours()), }) } // Sorting SyncManager Tasks by time. checkinparse.SortByTime(stl) for _, st := range stl { out.SyncTasks = append(out.SyncTasks, ActivityData{ Name: st.Name, UID: st.UID, Count: st.Count, CountPerHour: st.Count / float32(realtime.Hours()), Duration: st.Duration, SecondsPerHr: float32(st.Duration.Seconds()) / float32(realtime.Hours()), }) out.TotalAppSyncsPerHr += float32(st.Duration.Seconds()) / float32(realtime.Hours()) } // Sorting Partial Wakelocks by time. checkinparse.SortByTime(pwl) for _, pw := range pwl { out.UserspaceWakelocks = append(out.UserspaceWakelocks, ActivityData{ Name: pw.Name, UID: pw.UID, Count: pw.Count, CountPerHour: pw.Count / float32(realtime.Hours()), Duration: pw.Duration, SecondsPerHr: float32(pw.Duration.Seconds()) / float32(realtime.Hours()), }) } // Sort GPS use by time. checkinparse.SortByTime(gps) for _, g := range gps { out.GPSUse = append(out.GPSUse, ActivityData{ Name: g.Name, UID: g.UID, Count: g.Count, CountPerHour: g.Count / float32(realtime.Hours()), Duration: g.Duration, SecondsPerHr: float32(g.Duration.Seconds()) / float32(realtime.Hours()), }) out.TotalAppGPSUseTimePerHour += float32(g.Duration.Seconds()) / float32(realtime.Hours()) } // Sort camera use by time. checkinparse.SortByTime(ca) for _, c := range ca { out.CameraUse = append(out.CameraUse, ActivityData{ Name: c.Name, UID: c.UID, Count: c.Count, CountPerHour: c.Count / float32(realtime.Hours()), Duration: c.Duration, SecondsPerHr: float32(c.Duration.Seconds()) / float32(realtime.Hours()), }) out.TotalAppCameraUsePerHr += float32(c.Duration.Seconds()) / float32(realtime.Hours()) } // Sort flashlight use by time. checkinparse.SortByTime(fla) for _, f := range fla { out.FlashlightUse = append(out.FlashlightUse, ActivityData{ Name: f.Name, UID: f.UID, Count: f.Count, CountPerHour: f.Count / float32(realtime.Hours()), Duration: f.Duration, SecondsPerHr: float32(f.Duration.Seconds()) / float32(realtime.Hours()), }) out.TotalAppFlashlightUsePerHr += float32(f.Duration.Seconds()) / float32(realtime.Hours()) } return out }
// NormalizeStats takes in a proto and normalizes it by converting // any absolute value to value/TotalTime. func NormalizeStats(p *bspb.BatteryStats) (*bspb.BatteryStats, error) { totalTimeHour := roundToTwoDecimal(float64((p.GetSystem().GetBattery().GetBatteryRealtimeMsec()) / (3600 * 1000))) if totalTimeHour == 0 { return nil, errors.New("battery real time cannot be 0") } normApp := &bspb.BatteryStats{ ReportVersion: p.ReportVersion, AggregationType: p.AggregationType, } // Normalize the app data for _, a1 := range p.GetApp() { a := normalizeApp(a1, totalTimeHour) normApp.App = append(normApp.App, a) } // Normalize system data s1 := p.GetSystem() s := &bspb.BatteryStats_System{} if norm := normalizeMessage(s1.GetBattery(), totalTimeHour); norm != nil { s.Battery = norm.(*bspb.BatteryStats_System_Battery) } if norm := normalizeMessage(s1.GetBatteryDischarge(), totalTimeHour); norm != nil { s.BatteryDischarge = norm.(*bspb.BatteryStats_System_BatteryDischarge) } s.BatteryLevel = s1.GetBatteryLevel() if norm := normalizeRepeatedMessage(s1.GetBluetoothState(), totalTimeHour); !norm.IsNil() { s.BluetoothState = norm.Interface().([]*bspb.BatteryStats_System_BluetoothState) } if norm := normalizeRepeatedMessage(s1.GetDataConnection(), totalTimeHour); !norm.IsNil() { s.DataConnection = norm.Interface().([]*bspb.BatteryStats_System_DataConnection) } if norm := normalizeMessage(s1.GetGlobalNetwork(), totalTimeHour); norm != nil { s.GlobalNetwork = norm.(*bspb.BatteryStats_System_GlobalNetwork) } if norm := normalizeRepeatedMessage(s1.GetKernelWakelock(), totalTimeHour); !norm.IsNil() { s.KernelWakelock = norm.Interface().([]*bspb.BatteryStats_System_KernelWakelock) } if norm := normalizeMessage(s1.GetMisc(), totalTimeHour); norm != nil { s.Misc = norm.(*bspb.BatteryStats_System_Misc) } if norm := normalizeRepeatedMessage(s1.GetPowerUseItem(), totalTimeHour); !norm.IsNil() { s.PowerUseItem = norm.Interface().([]*bspb.BatteryStats_System_PowerUseItem) } if norm := normalizeMessage(s1.GetPowerUseSummary(), totalTimeHour); norm != nil { s.PowerUseSummary = norm.(*bspb.BatteryStats_System_PowerUseSummary) } if norm := normalizeRepeatedMessage(s1.GetScreenBrightness(), totalTimeHour); !norm.IsNil() { s.ScreenBrightness = norm.Interface().([]*bspb.BatteryStats_System_ScreenBrightness) } if norm := normalizeMessage(s1.GetSignalScanningTime(), totalTimeHour); norm != nil { s.SignalScanningTime = norm.(*bspb.BatteryStats_System_SignalScanningTime) } if norm := normalizeRepeatedMessage(s1.GetSignalStrength(), totalTimeHour); !norm.IsNil() { s.SignalStrength = norm.Interface().([]*bspb.BatteryStats_System_SignalStrength) } if norm := normalizeRepeatedMessage(s1.GetWakeupReason(), totalTimeHour); !norm.IsNil() { s.WakeupReason = norm.Interface().([]*bspb.BatteryStats_System_WakeupReason) } if norm := normalizeRepeatedMessage(s1.GetWifiState(), totalTimeHour); !norm.IsNil() { s.WifiState = norm.Interface().([]*bspb.BatteryStats_System_WifiState) } if norm := normalizeRepeatedMessage(s1.GetWifiSupplicantState(), totalTimeHour); !norm.IsNil() { s.WifiSupplicantState = norm.Interface().([]*bspb.BatteryStats_System_WifiSupplicantState) } p.System = s p.App = normApp.App return p, nil }
func parseCheckinData(c *bspb.BatteryStats) checkin { if c == nil { return checkin{} } realtime := time.Duration(c.System.Battery.GetBatteryRealtimeMsec()) * time.Millisecond out := checkin{ Device: c.Build.GetDevice(), Build: c.Build.GetBuildId(), BuildFingerprint: c.Build.GetFingerprint(), ReportVersion: c.GetReportVersion(), Realtime: realtime, ScreenOffRealtime: time.Duration(c.System.Battery.GetScreenOffRealtimeMsec()) * time.Millisecond, ScreenOffDischargePoints: c.System.BatteryDischarge.GetScreenOff(), ScreenOnDischargePoints: c.System.BatteryDischarge.GetScreenOn(), BatteryCapacity: c.System.PowerUseSummary.GetBatteryCapacityMah(), EstimatedDischarge: c.System.PowerUseSummary.GetComputedPowerMah(), ActualDischarge: (c.System.PowerUseSummary.GetMinDrainedPowerMah() + c.System.PowerUseSummary.GetMaxDrainedPowerMah()) / 2, // Uptime is the same as screen-off uptime + screen on time Uptime: mDuration{ V: (time.Duration(c.System.Battery.GetBatteryUptimeMsec()) * time.Millisecond), }, ScreenOffUptime: mDuration{ V: (time.Duration(c.System.Battery.GetScreenOffUptimeMsec()) * time.Millisecond), }, ScreenOnTime: mDuration{ V: (time.Duration(c.System.Misc.GetScreenOnTimeMsec()) * time.Millisecond), }, PartialWakelockTime: mDuration{ V: (time.Duration(c.System.Misc.GetPartialWakelockTimeMsec()) * time.Millisecond), }, KernelOverheadTime: mDuration{ V: (time.Duration(c.System.Battery.GetScreenOffUptimeMsec()-c.System.Misc.GetPartialWakelockTimeMsec()) * time.Millisecond), }, SignalScanningTime: mDuration{ V: (time.Duration(c.System.SignalScanningTime.GetTimeMsec()) * time.Millisecond), }, MobileActiveTime: mDuration{ V: (time.Duration(c.System.Misc.GetMobileActiveTimeMsec()) * time.Millisecond), }, } out.MiscPercentage = 100 * (out.ActualDischarge - out.EstimatedDischarge) / out.BatteryCapacity out.MobileKiloBytesPerHr = mFloat32{V: (c.System.GlobalNetwork.GetMobileBytesRx() + c.System.GlobalNetwork.GetMobileBytesTx()) / (1024 * float32(realtime.Hours()))} out.WifiKiloBytesPerHr = mFloat32{V: (c.System.GlobalNetwork.GetWifiBytesRx() + c.System.GlobalNetwork.GetWifiBytesTx()) / (1024 * float32(realtime.Hours()))} if c.GetReportVersion() >= 14 { out.WifiOnTime = mDuration{V: time.Duration(c.System.GlobalWifi.GetWifiOnTimeMsec()) * time.Millisecond} out.WifiIdleTime = mDuration{V: time.Duration(c.System.GlobalWifi.GetWifiIdleTimeMsec()) * time.Millisecond} out.WifiTransmitTime = mDuration{V: time.Duration(c.System.GlobalWifi.GetWifiRxTimeMsec()+c.System.GlobalWifi.GetWifiTxTimeMsec()) * time.Millisecond} out.WifiDischargePoints = 100 * c.System.GlobalWifi.GetWifiPowerMah() / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() out.WifiDischargeRatePerHr = mFloat32{ V: 100 * c.System.GlobalWifi.GetWifiPowerMah() / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() / float32(realtime.Hours()), } out.BluetoothIdleTime = mDuration{V: time.Duration(c.System.GlobalBluetooth.GetBluetoothIdleTimeMsec()) * time.Millisecond} out.BluetoothTransmitTime = mDuration{V: time.Duration(c.System.GlobalBluetooth.GetBluetoothRxTimeMsec()+c.System.GlobalBluetooth.GetBluetoothTxTimeMsec()) * time.Millisecond} out.BluetoothDischargePoints = 100 * c.System.GlobalBluetooth.GetBluetoothPowerMah() / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() out.BluetoothDischargeRatePerHr = mFloat32{ V: 100 * c.System.GlobalBluetooth.GetBluetoothPowerMah() / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah() / float32(realtime.Hours()), } } if s := c.System.Battery.GetScreenOffRealtimeMsec(); s > 0 { out.ScreenOffDichargeRatePerHr = mFloat32{V: 60 * 60 * 1000 * c.System.BatteryDischarge.GetScreenOff() / s} } if s := c.System.Misc.GetScreenOnTimeMsec(); s > 0 { out.ScreenOnDichargeRatePerHr = mFloat32{V: 60 * 60 * 1000 * c.System.BatteryDischarge.GetScreenOn() / s} } // Top Partial Wakelocks by time and count var pwl []*checkinparse.WakelockInfo for _, app := range c.App { for _, pw := range app.Wakelock { if pw.GetPartialTimeMsec() >= 0.01 { pwl = append(pwl, &checkinparse.WakelockInfo{ Name: fmt.Sprintf("%s : %s", app.GetName(), pw.GetName()), UID: app.GetUid(), Duration: time.Duration(pw.GetPartialTimeMsec()) * time.Millisecond, Count: pw.GetPartialCount(), }) } } } // Top Partial Wakelocks by time checkinparse.SortByTime(pwl) for _, pw := range pwl { out.UserspaceWakelocks = append(out.UserspaceWakelocks, WakelockData{ Name: pw.Name, UID: pw.UID, Count: pw.Count, Duration: pw.Duration, }) } // Top 5 Kernel Wakelocks var kwl []*checkinparse.WakelockInfo for _, kw := range c.System.KernelWakelock { if kw.GetName() != "PowerManagerService.WakeLocks" && kw.GetTimeMsec() >= 0.01 { kwl = append(kwl, &checkinparse.WakelockInfo{ Name: kw.GetName(), Duration: time.Duration(kw.GetTimeMsec()) * time.Millisecond, Count: kw.GetCount(), }) } } // Top Kernel Wakelocks by time checkinparse.SortByTime(kwl) for _, kw := range kwl { out.KernelWakelocks = append(out.KernelWakelocks, WakelockData{ Name: kw.Name, Count: kw.Count, Duration: kw.Duration, }) } // Top SyncTasks by time and count var stl []*checkinparse.WakelockInfo for _, app := range c.App { for _, st := range app.Sync { if st.GetTotalTimeMsec() >= 0.01 { stl = append(stl, &checkinparse.WakelockInfo{ Name: fmt.Sprintf("%s : %s", app.GetName(), st.GetName()), UID: app.GetUid(), Duration: time.Duration(st.GetTotalTimeMsec()) * time.Millisecond, Count: st.GetCount(), }) } } } // Top SyncTasks by time checkinparse.SortByTime(stl) for _, st := range stl { out.SyncTasks = append(out.SyncTasks, WakelockData{ Name: st.Name, UID: st.UID, Count: st.Count, Duration: st.Duration, }) } // Top power consumers and network users var e []*PowerUseData var m []*MobileActiveData var n []*NetworkTrafficData for _, app := range c.App { if mah := app.PowerUseItem.GetComputedPowerMah(); mah >= 0.01 { e = append(e, &PowerUseData{ Name: app.GetName(), UID: app.GetUid(), Percent: 100 * mah / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah(), }) } if mat := app.Network.GetMobileActiveTimeMsec(); mat >= 0.01 { m = append(m, &MobileActiveData{ Name: app.GetName(), UID: app.GetUid(), Duration: time.Duration(mat) * time.Millisecond, }) } wr := app.Network.GetWifiBytesRx() wt := app.Network.GetWifiBytesTx() mt := app.Network.GetMobileBytesTx() mr := app.Network.GetMobileBytesRx() if wr+wt+mt+mr >= 0.01 { n = append(n, &NetworkTrafficData{ Name: app.GetName(), UID: app.GetUid(), WifiMegaBytes: (wr + wt) / (1024 * 1024), MobileMegaBytes: (mr + mt) / (1024 * 1024), }) } } for _, pwi := range c.System.PowerUseItem { if pwi.GetName() == bspb.BatteryStats_System_PowerUseItem_APP { // We have the apps split up in the preceding for loop, and the APP entry is just the sum of all of them, so we skip it here. continue } if mah := pwi.GetComputedPowerMah(); mah >= 0.01 { e = append(e, &PowerUseData{ Name: pwi.GetName().String(), Percent: 100 * mah / c.GetSystem().GetPowerUseSummary().GetBatteryCapacityMah(), }) } } sort.Sort(byPercent(e)) for _, ent := range e { out.TopBatteryConsumingEntities = append(out.TopBatteryConsumingEntities, *ent) } sort.Sort(byTime(m)) for _, mad := range m { out.TopMobileActiveApps = append(out.TopMobileActiveApps, *mad) } sort.Sort(byMobileBytes(n)) for _, ntd := range n { if ntd.MobileMegaBytes >= 0.01 { out.TopMobileTrafficApps = append(out.TopMobileTrafficApps, *ntd) } } sort.Sort(byWifiBytes(n)) for _, ntd := range n { if ntd.WifiMegaBytes >= 0.01 { out.TopWifiTrafficApps = append(out.TopWifiTrafficApps, *ntd) } } return out }