func subtractApp(a1, a2 *bspb.BatteryStats_App) *bspb.BatteryStats_App { // The app name may be empty for one of the inputs, // if that file does not contain any occurence for this particular app // Here we extract the valid name from the 2 protos appName := a1.GetName() if appName == "" { appName = a2.GetName() } a := &bspb.BatteryStats_App{ Name: proto.String(appName), Uid: proto.Int32(a1.GetUid()), VersionName: combineProtoStrings(a1.GetVersionName(), a2.GetVersionName(), connector), VersionCode: a1.VersionCode, } c2map := make(map[string]*bspb.BatteryStats_App_Child) for _, c := range a2.GetChild() { c2map[c.GetName()] = c } changed := false if diff := subtractMessage(a1.GetCpu(), a2.GetCpu()); diff != nil { a.Cpu = diff.(*bspb.BatteryStats_App_Cpu) changed = true } if diff := subtractMessage(a1.GetForeground(), a2.GetForeground()); diff != nil { a.Foreground = diff.(*bspb.BatteryStats_App_Foreground) changed = true } if diff := subtractAppApk(a1.GetApk(), a2.GetApk()); diff != nil { a.Apk = diff changed = true } if diff := subtractController(a1.GetBluetoothController(), a2.GetBluetoothController()); diff != nil { a.BluetoothController = diff changed = true } if diff := subtractController(a1.GetModemController(), a2.GetModemController()); diff != nil { a.ModemController = diff changed = true } if diff := subtractMessage(a1.GetNetwork(), a2.GetNetwork()); diff != nil { a.Network = diff.(*bspb.BatteryStats_App_Network) changed = true } if diff := subtractMessage(a1.GetPowerUseItem(), a2.GetPowerUseItem()); diff != nil { a.PowerUseItem = diff.(*bspb.BatteryStats_App_PowerUseItem) changed = true } if diff := subtractRepeatedMessage(a1.GetProcess(), a2.GetProcess()); !diff.IsNil() { a.Process = diff.Interface().([]*bspb.BatteryStats_App_Process) changed = true } if diff := subtractRepeatedMessage(a1.GetSensor(), a2.GetSensor()); !diff.IsNil() { a.Sensor = diff.Interface().([]*bspb.BatteryStats_App_Sensor) changed = true } if diff := subtractMessage(a1.GetStateTime(), a2.GetStateTime()); diff != nil { a.StateTime = diff.(*bspb.BatteryStats_App_StateTime) changed = true } if diff := subtractMessage(a1.GetVibrator(), a2.GetVibrator()); diff != nil { a.Vibrator = diff.(*bspb.BatteryStats_App_Vibrator) changed = true } if diff := subtractRepeatedMessage(a1.GetWakelock(), a2.GetWakelock()); !diff.IsNil() { a.Wakelock = diff.Interface().([]*bspb.BatteryStats_App_Wakelock) changed = true } if diff := subtractMessage(a1.GetWifi(), a2.GetWifi()); diff != nil { a.Wifi = diff.(*bspb.BatteryStats_App_Wifi) changed = true } if diff := subtractController(a1.GetWifiController(), a2.GetWifiController()); diff != nil { a.WifiController = diff changed = true } if diff := subtractRepeatedMessage(a1.GetSync(), a2.GetSync()); !diff.IsNil() { a.Sync = diff.Interface().([]*bspb.BatteryStats_App_Sync) changed = true } if diff := subtractRepeatedMessage(a1.GetUserActivity(), a2.GetUserActivity()); !diff.IsNil() { a.UserActivity = diff.Interface().([]*bspb.BatteryStats_App_UserActivity) changed = true } if diff := subtractRepeatedMessage(a1.GetScheduledJob(), a2.GetScheduledJob()); !diff.IsNil() { a.ScheduledJob = diff.Interface().([]*bspb.BatteryStats_App_ScheduledJob) changed = true } for _, c := range a1.GetChild() { if c2, ok := c2map[c.GetName()]; ok { if diff := subtractAppChild(c, c2); diff != nil { a.Child = append(a.Child, diff) changed = true } delete(c2map, c.GetName()) } else { // Child doesn't exist in a2 a.Child = append(a.Child, c) changed = true } } for _, c2 := range c2map { // These children aren't in a1 a.Child = append(a.Child, c2) changed = true } // Subtract the head child h1 := a1.GetHeadChild() h2 := a2.GetHeadChild() if h1 != nil || h2 != nil { if h1 == nil { a.HeadChild = h2 changed = true } else if h2 == nil { a.HeadChild = h1 changed = true } else { if diff := subtractAppChild(a1.GetHeadChild(), a2.GetHeadChild()); diff != nil { a.HeadChild = diff changed = true } } } if !changed { return nil } return a }