| Index: src/data_plan.cc
|
| diff --git a/src/data_plan.cc b/src/data_plan.cc
|
| index 29a23d14909381953947865838ca93b606ebc11d..0be2daadf681846470687791e47e0516e3bdbe03 100644
|
| --- a/src/data_plan.cc
|
| +++ b/src/data_plan.cc
|
| @@ -8,7 +8,9 @@
|
|
|
| #include <glog/logging.h>
|
|
|
| +#include "src/device.h"
|
| #include "src/policy.h"
|
| +#include "src/service_manager.h"
|
|
|
| namespace cashew {
|
|
|
| @@ -44,8 +46,8 @@ static const char *kCrosUsageDataPlanTypeMeteredPaid = "METERED_PAID";
|
|
|
| DataPlan::DataPlan(const std::string& name, DataPlan::Type type,
|
| base::Time update_time, base::Time start_time,
|
| - base::Time end_time, Bytes data_bytes_max,
|
| - Bytes data_bytes_used)
|
| + base::Time end_time, ByteCount data_bytes_max,
|
| + ByteCount data_bytes_used)
|
| : name_(name), type_(type), update_time_(update_time),
|
| start_time_(start_time), end_time_(end_time),
|
| data_bytes_max_(data_bytes_max), data_bytes_used_(data_bytes_used),
|
| @@ -77,23 +79,25 @@ base::Time DataPlan::GetEndTime() const {
|
| return end_time_;
|
| }
|
|
|
| -Bytes DataPlan::GetDataBytesMax() const {
|
| +ByteCount DataPlan::GetDataBytesMax() const {
|
| return data_bytes_max_;
|
| }
|
|
|
| -Bytes DataPlan::GetDataBytesUsed() const {
|
| +ByteCount DataPlan::GetDataBytesUsed() const {
|
| return data_bytes_used_;
|
| }
|
|
|
| -Bytes DataPlan::GetLocalBytesUsed() const {
|
| +ByteCount DataPlan::GetLocalBytesUsed() const {
|
| return local_bytes_used_;
|
| }
|
|
|
| -Bytes DataPlan::GetTotalBytesUsed() const {
|
| +ByteCount DataPlan::GetTotalBytesUsed() const {
|
| return total_bytes_used_;
|
| }
|
|
|
| -void DataPlan::SetLocalBytesUsed(Bytes local_bytes_used) {
|
| +// TODO(vlaviano): ensure that this method stops the plan's expiration timer
|
| +// (when it is implemented in a future CL) if the plan is fully consumed
|
| +void DataPlan::SetLocalBytesUsed(ByteCount local_bytes_used) {
|
| CHECK_GE(local_bytes_used, 0);
|
| local_bytes_used_ = local_bytes_used;
|
| total_bytes_used_ = data_bytes_used_ + local_bytes_used_;
|
| @@ -316,6 +320,105 @@ DataPlan* DataPlan::GetActivePlan(const DataPlanList& data_plans) {
|
| return NULL;
|
| }
|
|
|
| +// static
|
| +bool DataPlan::OnByteCounterUpdate(DataPlanList *data_plans, Service *service,
|
| + ServiceManager *service_manager,
|
| + Device *device, uint64 rx_bytes,
|
| + uint64 tx_bytes) {
|
| + DCHECK(data_plans != NULL);
|
| + DCHECK(service != NULL);
|
| + DCHECK(service_manager != NULL);
|
| + DCHECK(device != NULL);
|
| + DCHECK(device->ByteCounterRunning());
|
| + DLOG(INFO) << "OnByteCounterUpdate: rx_bytes = " << rx_bytes
|
| + << ", tx_bytes = " << tx_bytes;
|
| + DataPlan *active_plan = DataPlan::GetActivePlan(*data_plans);
|
| + if (active_plan == NULL) {
|
| + DLOG(WARNING) << "OnByteCounterUpdate: no active plan";
|
| + device->StopByteCounter();
|
| + return false;
|
| + }
|
| + ByteCount local_bytes_used = rx_bytes + tx_bytes;
|
| + DLOG(INFO) << "OnByteCounterUpdate: local_bytes_used = " << local_bytes_used;
|
| + // try to detect two error conditions:
|
| + // (1) overflow of the unsigned addition above prior to the assignment
|
| + // (2) no overflow, but result has high order bit set and so is interpreted as
|
| + // a negative number when assigned to |local_bytes_used|
|
| + if (local_bytes_used < 0 ||
|
| + static_cast<uint64>(local_bytes_used) < rx_bytes ||
|
| + static_cast<uint64>(local_bytes_used) < tx_bytes) {
|
| + LOG(WARNING) << "OnByteCounterUpdate: overflow detected";
|
| + return false;
|
| + }
|
| + // compute delta since last sample
|
| + // this delta represents the data usage that we need to assign to active plans
|
| + // this computation relies on the local counter being based on the currently
|
| + // active plan
|
| + // TODO(vlaviano): Currently, this is not always true. It's possible for the
|
| + // local byte counter to be associated with a plan that was active at the
|
| + // beginning of the sample interval but has now expired. A future CL will
|
| + // add expiration timers to plan objects to handle this case.
|
| + ByteCount previous_local_bytes_used = active_plan->GetLocalBytesUsed();
|
| + DLOG(INFO) << "OnByteCounterUpdate: previous_local_bytes_used = "
|
| + << previous_local_bytes_used;
|
| + DCHECK_LE(previous_local_bytes_used, local_bytes_used);
|
| + ByteCount used_bytes_to_assign = local_bytes_used - previous_local_bytes_used;
|
| + DLOG(INFO) << "OnByteCounterUpdate: used_bytes_to_assign = "
|
| + << used_bytes_to_assign;
|
| + // iterate through active plans, assigning as much data as possible to each
|
| + // plan and expiring it if its data quota is fully consumed
|
| + ByteCount assigned_bytes = 0;
|
| + bool any_plan_updated = false;
|
| + while (used_bytes_to_assign > 0 && active_plan != NULL) {
|
| + ByteCount active_plan_data_remaining = 0; // relevant for metered plans
|
| + if (active_plan->GetType() != DataPlan::kTypeUnlimited) {
|
| + active_plan_data_remaining = active_plan->GetDataBytesMax() -
|
| + active_plan->GetTotalBytesUsed();
|
| + DCHECK_GE(active_plan_data_remaining, 0);
|
| + }
|
| + if (active_plan->GetType() == DataPlan::kTypeUnlimited ||
|
| + used_bytes_to_assign < active_plan_data_remaining) {
|
| + // can assign all data from this sample and plan not fully consumed
|
| + assigned_bytes = used_bytes_to_assign;
|
| + used_bytes_to_assign = 0;
|
| + } else {
|
| + // plan fully consumed, and there might be an overage remaining to be
|
| + // assigned to the next active plan
|
| + assigned_bytes = active_plan_data_remaining;
|
| + used_bytes_to_assign -= assigned_bytes;
|
| + }
|
| + DCHECK_GE(assigned_bytes, 0);
|
| + active_plan->SetLocalBytesUsed(previous_local_bytes_used + assigned_bytes);
|
| + any_plan_updated = true;
|
| + DLOG(INFO) << "OnByteCounterUpdate: " << active_plan->GetName()
|
| + << ": updated plan state: data bytes used = "
|
| + << active_plan->GetDataBytesUsed() << ", local bytes used = "
|
| + << active_plan->GetLocalBytesUsed() << ", total bytes used = "
|
| + << active_plan->GetTotalBytesUsed();
|
| +
|
| + if (!active_plan->IsActive()) {
|
| + // notify service manager that plan has become inactive
|
| + service_manager->OnDataPlanInactive(*service, *active_plan);
|
| +
|
| + // we've consumed a plan, so reset byte counter to only reflect overage
|
| + // TODO(vlaviano): byte counter api shouldn't expose rx/tx split.
|
| + device->ResetByteCounter(used_bytes_to_assign, 0);
|
| + active_plan = DataPlan::GetActivePlan(*data_plans);
|
| + }
|
| + }
|
| +
|
| + // if we have no more active plans, stop our local counter
|
| + if (active_plan == NULL) {
|
| + device->StopByteCounter();
|
| + // warn if we've measured usage beyond what should have been available
|
| + if (used_bytes_to_assign > 0) {
|
| + DLOG(WARNING) << "OnByteCounterUpdate: used_bytes_to_assign = "
|
| + << used_bytes_to_assign << ", but no active plan";
|
| + }
|
| + }
|
| + return any_plan_updated;
|
| +}
|
| +
|
| // private methods
|
|
|
| const char* DataPlan::TypeToLibcrosString(DataPlan::Type type) const {
|
|
|