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 
ModemManager1(ControlInterface * control_interface,const string & service,const string & path,ModemInfo * modem_info)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 
~ModemManager1()45 ModemManager1::~ModemManager1() {
46   Stop();
47 }
48 
Start()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 
Stop()66 void ModemManager1::Stop() {
67   LOG(INFO) << "Stop watching modem manager service: " << service();
68   proxy_.reset();
69   Disconnect();
70 }
71 
Connect()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 
Disconnect()82 void ModemManager1::Disconnect() {
83   ModemManager::Disconnect();
84 }
85 
AddModem1(const string & path,const InterfaceToProperties & properties)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 
InitModem1(shared_ptr<Modem1> modem,const InterfaceToProperties & properties)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
OnInterfacesAddedSignal(const string & object_path,const InterfaceToProperties & properties)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 
OnInterfacesRemovedSignal(const string & object_path,const vector<string> & interfaces)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
OnGetManagedObjectsReply(const ObjectsWithProperties & objects,const Error & error)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