Home | History | Annotate | Download | only in cellular
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/cellular/modem_manager.h"
     18 
     19 #include <base/bind.h>
     20 #include <base/stl_util.h>
     21 #include <ModemManager/ModemManager.h>
     22 
     23 #include "shill/cellular/modem.h"
     24 #include "shill/control_interface.h"
     25 #include "shill/error.h"
     26 #include "shill/logging.h"
     27 
     28 using base::Bind;
     29 using std::string;
     30 using std::shared_ptr;
     31 using std::vector;
     32 
     33 namespace shill {
     34 
     35 ModemManager1::ModemManager1(ControlInterface* control_interface,
     36                              const string& service,
     37                              const string& path,
     38                              ModemInfo* modem_info)
     39     : ModemManager(control_interface,
     40                    service,
     41                    path,
     42                    modem_info),
     43       weak_ptr_factory_(this) {}
     44 
     45 ModemManager1::~ModemManager1() {
     46   Stop();
     47 }
     48 
     49 void ModemManager1::Start() {
     50   LOG(INFO) << "Start watching modem manager service: " << service();
     51   CHECK(!proxy_);
     52   proxy_.reset(
     53       control_interface()->CreateDBusObjectManagerProxy(
     54           path(),
     55           service(),
     56           base::Bind(&ModemManager1::OnAppeared, base::Unretained(this)),
     57           base::Bind(&ModemManager1::OnVanished, base::Unretained(this))));
     58   proxy_->set_interfaces_added_callback(
     59       Bind(&ModemManager1::OnInterfacesAddedSignal,
     60            weak_ptr_factory_.GetWeakPtr()));
     61   proxy_->set_interfaces_removed_callback(
     62       Bind(&ModemManager1::OnInterfacesRemovedSignal,
     63            weak_ptr_factory_.GetWeakPtr()));
     64 }
     65 
     66 void ModemManager1::Stop() {
     67   LOG(INFO) << "Stop watching modem manager service: " << service();
     68   proxy_.reset();
     69   Disconnect();
     70 }
     71 
     72 void ModemManager1::Connect() {
     73   ModemManager::Connect();
     74   // TODO(rochberg):  Make global kDBusDefaultTimeout and use it here
     75   Error error;
     76   proxy_->GetManagedObjects(&error,
     77                             Bind(&ModemManager1::OnGetManagedObjectsReply,
     78                                  weak_ptr_factory_.GetWeakPtr()),
     79                             5000);
     80 }
     81 
     82 void ModemManager1::Disconnect() {
     83   ModemManager::Disconnect();
     84 }
     85 
     86 void ModemManager1::AddModem1(const string& path,
     87                               const InterfaceToProperties& properties) {
     88   if (ModemExists(path)) {
     89     return;
     90   }
     91   shared_ptr<Modem1> modem1(new Modem1(service(),
     92                                        path,
     93                                        modem_info(),
     94                                        control_interface()));
     95   RecordAddedModem(modem1);
     96   InitModem1(modem1, properties);
     97 }
     98 
     99 void ModemManager1::InitModem1(shared_ptr<Modem1> modem,
    100                                const InterfaceToProperties& properties) {
    101   if (modem == nullptr) {
    102     return;
    103   }
    104   modem->CreateDeviceMM1(properties);
    105 }
    106 
    107 // signal methods
    108 // Also called by OnGetManagedObjectsReply
    109 void ModemManager1::OnInterfacesAddedSignal(
    110     const string& object_path,
    111     const InterfaceToProperties& properties) {
    112   if (ContainsKey(properties, MM_DBUS_INTERFACE_MODEM)) {
    113     AddModem1(object_path, properties);
    114   } else {
    115     LOG(ERROR) << "Interfaces added, but not modem interface.";
    116   }
    117 }
    118 
    119 void ModemManager1::OnInterfacesRemovedSignal(
    120     const string& object_path,
    121     const vector<string>& interfaces) {
    122   LOG(INFO) << "MM1:  Removing interfaces from " << object_path;
    123   if (find(interfaces.begin(),
    124            interfaces.end(),
    125            MM_DBUS_INTERFACE_MODEM) != interfaces.end()) {
    126     RemoveModem(object_path);
    127   } else {
    128     // In theory, a modem could drop, say, 3GPP, but not CDMA.  In
    129     // practice, we don't expect this
    130     LOG(ERROR) << "Interfaces removed, but not modem interface";
    131   }
    132 }
    133 
    134 // DBusObjectManagerProxy async method call
    135 void ModemManager1::OnGetManagedObjectsReply(
    136     const ObjectsWithProperties& objects,
    137     const Error& error) {
    138   if (error.IsSuccess()) {
    139     ObjectsWithProperties::const_iterator m;
    140     for (m = objects.begin(); m != objects.end(); ++m) {
    141       OnInterfacesAddedSignal(m->first, m->second);
    142     }
    143   }
    144 }
    145 
    146 }  // namespace shill
    147