func main() { flag.Parse() c, err := ioutil.ReadFile(*inputFile) if err != nil { log.Fatalf("Cannot open the file %s: %v", *inputFile, err) } br, fname, err := bugreportutils.ExtractBugReport(*inputFile, c) if err != nil { log.Fatalf("Error getting file contents: %v", err) } fmt.Printf("Parsing %s\n", fname) bs := bugreportutils.ExtractBatterystatsCheckin(br) if strings.Contains(bs, "Exception occurred while dumping") { log.Fatalf("Exception found in battery dump.") } m, err := bugreportutils.ParseMetaInfo(br) if err != nil { log.Fatalf("Unable to get meta info: %v", err) } s := &sessionpb.Checkin{ Checkin: proto.String(bs), BuildFingerprint: proto.String(m.BuildFingerprint), } pkgs, errs := packageutils.ExtractAppsFromBugReport(br) if len(errs) > 0 { log.Fatalf("Errors encountered when getting package list: %v", errs) } var ctr checkinutil.IntCounter stats, warns, errs := checkinparse.ParseBatteryStats(&ctr, checkinparse.CreateCheckinReport(s), pkgs) if len(warns) > 0 { log.Printf("Encountered unexpected warnings: %v\n", warns) } if len(errs) > 0 { log.Fatalf("Could not parse battery stats: %v\n", errs) } fmt.Println("\n################\n") fmt.Println("Partial Wakelocks") fmt.Println("################\n") var pwl []*checkinparse.WakelockInfo for _, app := range stats.App { for _, pw := range app.Wakelock { if pw.GetPartialTimeMsec() > 0 { 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.SortByTime(pwl) for _, pw := range pwl[:min(5, len(pwl))] { fmt.Printf("%s (uid=%d) %s\n", pw.Duration, pw.UID, pw.Name) } fmt.Println("\n################") fmt.Println("Kernel Wakelocks") fmt.Println("################\n") var kwl []*checkinparse.WakelockInfo for _, kw := range stats.System.KernelWakelock { if kw.GetName() != "PowerManagerService.WakeLocks" && kw.GetTimeMsec() > 0 { kwl = append(kwl, &checkinparse.WakelockInfo{ Name: kw.GetName(), Duration: time.Duration(kw.GetTimeMsec()) * time.Millisecond, }) } } checkinparse.SortByTime(kwl) for _, kw := range kwl[:min(5, len(kwl))] { fmt.Printf("%s %s\n", kw.Duration, kw.Name) } data, err := proto.Marshal(stats) if err != nil { log.Fatalf("Error from proto.Marshal: %v", err) } ioutil.WriteFile("checkin.proto", data, 0600) }
// 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 }
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 }