| Index: src/service.cc
|
| diff --git a/src/service.cc b/src/service.cc
|
| index 3d0f808257afa542c53cbaddb3e2c124d622e08f..84c12be8754676a670ac89e54414847d33badf8d 100644
|
| --- a/src/service.cc
|
| +++ b/src/service.cc
|
| @@ -21,6 +21,8 @@ static const char *kFlimflamServiceDeviceProperty = "Device";
|
| static const char *kFlimflamServiceStateProperty = "State";
|
| static const char *kFlimflamServiceTypeProperty = "Type";
|
| static const char *kFlimflamServiceUsageUrlProperty = "Cellular.UsageUrl";
|
| +static const char *kFlimflamServiceRestrictedPoolProperty =
|
| + "Cellular.RestrictedPool";
|
|
|
| // Flimflam Service on-the-wire State values
|
| static const char *kFlimflamServiceStateIdle = "idle";
|
| @@ -73,7 +75,7 @@ Service::Service(ServiceManager * const parent,
|
| provider_(NULL), request_in_progress_(false),
|
| update_timeout_source_(NULL), policy_(NULL),
|
| is_default_service_(false), get_properties_source_id_(0),
|
| - retrying_get_properties_(false) {
|
| + retrying_get_properties_(false), restricted_pool_(false) {
|
| // schedule a GetProperties() call to our Flimflam service path to init state
|
| // we'll keep trying periodically until we succeed
|
| // we'll subsequently update this state by monitoring PropertyChanged signals
|
| @@ -157,6 +159,13 @@ bool Service::IsDefaultService() const {
|
| return false;
|
| }
|
|
|
| +bool Service::RestrictedPool() const {
|
| + // NOTE: For now, we rely strictly on the Cellular.RestrictedPool Flimflam
|
| + // Service property, and we ignore the optional 'restricted' boolean that's
|
| + // defined as part of the usage API.
|
| + return restricted_pool_;
|
| +}
|
| +
|
| // Flimflam Service D-Bus Proxy methods
|
|
|
| void Service::PropertyChanged(const std::string& property_name,
|
| @@ -170,6 +179,8 @@ void Service::PropertyChanged(const std::string& property_name,
|
| OnTypeUpdate(new_value.reader().get_string());
|
| } else if (property_name == kFlimflamServiceUsageUrlProperty) {
|
| OnUsageUrlUpdate(new_value.reader().get_string());
|
| + } else if (property_name == kFlimflamServiceRestrictedPoolProperty) {
|
| + OnRestrictedPoolUpdate(new_value.reader().get_bool());
|
| } else {
|
| // we don't care about this property
|
| }
|
| @@ -179,8 +190,8 @@ void Service::PropertyChanged(const std::string& property_name,
|
|
|
| void Service::OnCarrierUpdate(const std::string& carrier) {
|
| DLOG(INFO) << path_ << ": OnCarrierUpdate: carrier = " << carrier;
|
| - // NOTE: device_ can be NULL here because we may still be in Device ctor
|
| - DCHECK(device_ == NULL || carrier == device_->GetCarrier());
|
| + DCHECK(device_ != NULL);
|
| + DCHECK(carrier == device_->GetCarrier());
|
|
|
| // get rid of state associated with old carrier
|
| if (provider_ != NULL) {
|
| @@ -189,7 +200,7 @@ void Service::OnCarrierUpdate(const std::string& carrier) {
|
| DeleteCarrierState();
|
|
|
| // if we don't have new carrier info, we can't do anything now
|
| - if (carrier == Device::kCarrierUnknown) {
|
| + if (carrier.empty()) {
|
| return;
|
| }
|
|
|
| @@ -220,6 +231,33 @@ void Service::OnCarrierUpdate(const std::string& carrier) {
|
| }
|
| }
|
|
|
| +void Service::OnByteCounterUpdate(uint64 rx_bytes, uint64 tx_bytes) {
|
| + DCHECK(device_ != NULL);
|
| + DCHECK(device_->ByteCounterRunning());
|
| + DLOG(INFO) << path_ << ": OnByteCounterUpdate: rx_bytes = " << rx_bytes
|
| + << ", tx_bytes = " << tx_bytes;
|
| + DataPlan *active_plan = DataPlan::GetActivePlan(data_plans_);
|
| + if (active_plan == NULL) {
|
| + DLOG(WARNING) << path_ << ": OnByteCounterUpdate: no active plan";
|
| + return;
|
| + }
|
| + Bytes local_bytes_used = rx_bytes + tx_bytes;
|
| + DLOG(INFO) << path_ << ": 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) << path_ << ": OnByteCounterUpdate: overflow detected";
|
| + return;
|
| + }
|
| + active_plan->SetLocalBytesUsed(local_bytes_used);
|
| + MaybeEmitDataPlansUpdate();
|
| +}
|
| +
|
| // DataPlanProviderDelegate methods
|
|
|
| void Service::OnRequestComplete(const DataPlanProvider *provider,
|
| @@ -282,6 +320,8 @@ void Service::OnRequestComplete(const DataPlanProvider *provider,
|
| bool restricted = false;
|
| if (root->GetBoolean(kCrosUsageRestrictedProperty, &restricted)) {
|
| DLOG(INFO) << path_ << ": OnRequestComplete: restricted = " << restricted;
|
| + // TODO(vlaviano): this should probably take precedence over our
|
| + // Cellular.RestrictedPool property
|
| } else {
|
| DLOG(INFO) << path_ << ": OnRequestComplete: no restricted property";
|
| // restricted property is optional
|
| @@ -322,16 +362,29 @@ void Service::OnRequestComplete(const DataPlanProvider *provider,
|
| data_plans_ = new_plans;
|
| LOG(INFO) << path_ << ": OnRequestComplete: updated data plans";
|
|
|
| - // consult policy to determine if we should send an unsolicited update
|
| - if (policy_->ShouldEmitDataPlansUpdate(old_plans, new_plans)) {
|
| - DLOG(INFO) << path_ << ": OnRequestComplete: sending update";
|
| - parent_->EmitDataPlansUpdate(*this);
|
| - } else {
|
| - DLOG(INFO) << path_ << ": OnRequestComplete: not sending update";
|
| - }
|
| + MaybeEmitDataPlansUpdate();
|
|
|
| DLOG(INFO) << path_ << ": OnRequestComplete: deleting old data plans";
|
| DeleteDataPlans(&old_plans);
|
| +
|
| + // start local byte counter so that we can stop hitting usage API
|
| + // we'll stop the counter when we disconnect
|
| + // we don't bother if carrier told us that there are no active data plans
|
| + DataPlan *active_plan = DataPlan::GetActivePlan(data_plans_);
|
| + if (active_plan == NULL) {
|
| + DLOG(INFO) << path_
|
| + << ": OnRequestComplete: no active plans, not starting byte counter";
|
| + return;
|
| + }
|
| + DCHECK(device_ != NULL);
|
| + DCHECK(!device_->ByteCounterRunning());
|
| + if (!device_->StartByteCounter()) {
|
| + LOG(WARNING) << path_
|
| + << ": OnRequestComplete: could not start byte counter";
|
| + // we'll keep the update timer running and try again later
|
| + }
|
| + DLOG(INFO) << path_ << ": OnRequestComplete: started byte counter";
|
| + ReconsiderSendingUsageRequests();
|
| }
|
|
|
| // Service Manager methods
|
| @@ -471,6 +524,15 @@ void Service::OnUsageUrlUpdate(const std::string& usage_url) {
|
| }
|
| }
|
|
|
| +void Service::OnRestrictedPoolUpdate(bool restricted_pool) {
|
| + DLOG(INFO) << path_ << ": OnRestrictedPoolUpdate: restricted_pool = "
|
| + << restricted_pool;
|
| + if (restricted_pool == restricted_pool_) {
|
| + return;
|
| + }
|
| + ReconsiderSendingUsageRequests();
|
| +}
|
| +
|
| // static
|
| gboolean Service::StaticGetServicePropertiesCallback(gpointer data) {
|
| Service *service = reinterpret_cast<Service*>(data);
|
| @@ -564,6 +626,14 @@ bool Service::GetServiceProperties() {
|
| DLOG(WARNING) << path_
|
| << ": GetServiceProperties: no Cellular.UsageUrl property";
|
| }
|
| + it = properties.find(kFlimflamServiceRestrictedPoolProperty);
|
| + if (it != properties.end()) {
|
| + const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
|
| + OnRestrictedPoolUpdate(value.reader().get_bool());
|
| + } else {
|
| + DLOG(WARNING) << path_
|
| + << ": GetServiceProperties: no Cellular.RestrictedPool property";
|
| + }
|
| return true;
|
| }
|
|
|
| @@ -722,6 +792,11 @@ void Service::OnConnected() {
|
| void Service::OnDisconnected() {
|
| DLOG(INFO) << path_ << ": OnDisconnected";
|
| DCHECK(!IsConnected());
|
| + // stop byte counter
|
| + // we'll issue a new usage API request when we reconnect
|
| + if (device_ != NULL) {
|
| + device_->StopByteCounter();
|
| + }
|
| ReconsiderSendingUsageRequests();
|
| }
|
|
|
| @@ -737,7 +812,8 @@ bool Service::ShouldSendUsageRequests() const {
|
| DCHECK(policy_ == NULL);
|
| return false;
|
| }
|
| - DCHECK(device_ == NULL || device_->GetCarrier() != Device::kCarrierUnknown);
|
| + DCHECK(device_ != NULL);
|
| + DCHECK(!device_->GetCarrier().empty());
|
| DCHECK(policy_ != NULL);
|
| if (usage_url_.empty()) {
|
| DLOG(INFO) << path_ << ": ShouldSendUsageRequests: no: no usage url";
|
| @@ -749,17 +825,18 @@ bool Service::ShouldSendUsageRequests() const {
|
| << ": ShouldSendUsageRequests: no: flimflam is offline";
|
| return false;
|
| }
|
| - if (policy_->UsageRequestsMustBeSentOTA()) {
|
| - if (!IsConnected()) {
|
| - DLOG(INFO) << path_ << ": ShouldSendUsageRequests: no: "
|
| - << "ota-only policy and not connected";
|
| - return false;
|
| - }
|
| - if (!IsDefaultService()) {
|
| - DLOG(INFO) << path_ << ": ShouldSendUsageRequests: no: "
|
| - << "ota-only policy and not default service";
|
| - return false;
|
| - }
|
| + if (!IsConnected()) {
|
| + DLOG(INFO) << path_ << ": ShouldSendUsageRequests: no: not connected";
|
| + return false;
|
| + }
|
| + if (!IsDefaultService()) {
|
| + DLOG(INFO) << path_ << ": ShouldSendUsageRequests: no: not default service";
|
| + return false;
|
| + }
|
| + if (device_->ByteCounterRunning()) {
|
| + DLOG(INFO) << path_
|
| + << ": ShouldSendUsageRequests: no: local byte counter is running";
|
| + return false;
|
| }
|
| DLOG(INFO) << path_ << ": ShouldSendUsageRequests: yes";
|
| return true;
|
| @@ -787,4 +864,14 @@ void Service::ReconsiderSendingUsageRequests() {
|
| }
|
| }
|
|
|
| +void Service::MaybeEmitDataPlansUpdate() {
|
| + DCHECK(policy_ != NULL);
|
| + if (policy_->ShouldEmitDataPlansUpdate(data_plans_)) {
|
| + DLOG(INFO) << path_ << ": MaybeEmitDataPlansUpdate: sending update";
|
| + parent_->EmitDataPlansUpdate(*this);
|
| + } else {
|
| + DLOG(INFO) << path_ << ": MaybeEmitDataPlansUpdate: not sending update";
|
| + }
|
| +}
|
| +
|
| } // namespace cashew
|
|
|