blob: 1171a540645a9bcd77cddc0c25967619a679319d [file] [log] [blame]
//
// Copyright (C) 2012 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "shill/cellular/modem_manager.h"
#include <memory>
#include <utility>
#include <base/bind.h>
#include <base/stl_util.h>
#include <ModemManager/ModemManager.h>
#include "shill/cellular/modem.h"
#include "shill/control_interface.h"
#include "shill/error.h"
#include "shill/logging.h"
using base::Bind;
using std::string;
using std::vector;
namespace shill {
ModemManager1::ModemManager1(const string& service,
const string& path,
ModemInfo* modem_info)
: ModemManager(service, path, modem_info), weak_ptr_factory_(this) {}
ModemManager1::~ModemManager1() {
Stop();
}
void ModemManager1::Start() {
LOG(INFO) << "Start watching modem manager service: " << service();
CHECK(!proxy_);
proxy_ = control_interface()->CreateDBusObjectManagerProxy(
path(),
service(),
base::Bind(&ModemManager1::OnAppeared, base::Unretained(this)),
base::Bind(&ModemManager1::OnVanished, base::Unretained(this)));
proxy_->set_interfaces_added_callback(
Bind(&ModemManager1::OnInterfacesAddedSignal,
weak_ptr_factory_.GetWeakPtr()));
proxy_->set_interfaces_removed_callback(
Bind(&ModemManager1::OnInterfacesRemovedSignal,
weak_ptr_factory_.GetWeakPtr()));
}
void ModemManager1::Stop() {
LOG(INFO) << "Stop watching modem manager service: " << service();
proxy_.reset();
Disconnect();
}
void ModemManager1::Connect() {
ModemManager::Connect();
// TODO(rochberg): Make global kDBusDefaultTimeout and use it here
Error error;
proxy_->GetManagedObjects(&error,
Bind(&ModemManager1::OnGetManagedObjectsReply,
weak_ptr_factory_.GetWeakPtr()),
5000);
}
void ModemManager1::Disconnect() {
ModemManager::Disconnect();
}
void ModemManager1::AddModem1(const string& path,
const InterfaceToProperties& properties) {
if (ModemExists(path)) {
return;
}
auto modem = std::make_unique<Modem1>(service(), path, modem_info());
InitModem1(modem.get(), properties);
RecordAddedModem(std::move(modem));
}
void ModemManager1::InitModem1(Modem1* modem,
const InterfaceToProperties& properties) {
modem->CreateDeviceMM1(properties);
}
// signal methods
// Also called by OnGetManagedObjectsReply
void ModemManager1::OnInterfacesAddedSignal(
const string& object_path,
const InterfaceToProperties& properties) {
if (base::ContainsKey(properties, MM_DBUS_INTERFACE_MODEM)) {
AddModem1(object_path, properties);
} else {
LOG(ERROR) << "Interfaces added, but not modem interface.";
}
}
void ModemManager1::OnInterfacesRemovedSignal(
const string& object_path,
const vector<string>& interfaces) {
LOG(INFO) << "MM1: Removing interfaces from " << object_path;
if (find(interfaces.begin(),
interfaces.end(),
MM_DBUS_INTERFACE_MODEM) != interfaces.end()) {
RemoveModem(object_path);
} else {
// In theory, a modem could drop, say, 3GPP, but not CDMA. In
// practice, we don't expect this
LOG(ERROR) << "Interfaces removed, but not modem interface";
}
}
// DBusObjectManagerProxy async method call
void ModemManager1::OnGetManagedObjectsReply(
const ObjectsWithProperties& objects,
const Error& error) {
if (error.IsSuccess()) {
for (const auto& object_properties_pair : objects) {
OnInterfacesAddedSignal(object_properties_pair.first,
object_properties_pair.second);
}
}
}
} // namespace shill