blob: 670a004560691aad6cb316669221197668b1a013 [file] [log] [blame]
// Copyright (C) 2014 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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <base/cancelable_callback.h>
#include <base/files/file_util.h>
#include <base/memory/weak_ptr.h>
#include <base/observer_list.h>
#include "shill/cellular/mobile_operator_info.h"
#include "shill/event_dispatcher.h"
#include "shill/mobile_operator_db/mobile_operator_db.pb.h"
namespace shill {
class MobileOperatorInfoImpl {
using StringToMNOListMap =
std::vector<const mobile_operator_db::MobileNetworkOperator*>>;
// Delegates to private constructor
MobileOperatorInfoImpl(EventDispatcher* dispatcher,
const std::string& info_owner);
// API functions of the interface.
// See mobile_operator_info.h for details.
void ClearDatabasePaths();
void AddDatabasePath(const base::FilePath& absolute_path);
bool Init();
void AddObserver(MobileOperatorInfo::Observer* observer);
void RemoveObserver(MobileOperatorInfo::Observer* observer);
bool IsMobileNetworkOperatorKnown() const;
bool IsMobileVirtualNetworkOperatorKnown() const;
const std::string& info_owner() const;
const std::string& uuid() const;
const std::string& operator_name() const;
const std::string& country() const;
const std::string& mccmnc() const;
const std::string& sid() const;
const std::string& nid() const;
const std::vector<std::string>& mccmnc_list() const;
const std::vector<std::string>& sid_list() const;
const std::vector<MobileOperatorInfo::LocalizedName>
&operator_name_list() const;
const std::vector<std::unique_ptr<MobileOperatorInfo::MobileAPN>>& apn_list()
const std::vector<MobileOperatorInfo::OnlinePortal>& olp_list() const;
const std::string& activation_code() const;
bool requires_roaming() const;
void Reset();
void UpdateIMSI(const std::string& imsi);
void UpdateICCID(const std::string& iccid);
void UpdateMCCMNC(const std::string& mccmnc);
void UpdateSID(const std::string& sid);
void UpdateNID(const std::string& nid);
void UpdateOperatorName(const std::string& operator_name);
void UpdateOnlinePortal(const std::string& url,
const std::string& method,
const std::string& post_data);
friend class MobileOperatorInfoInitTest;
friend class MobileOperatorInfoOverrideTest;
// ///////////////////////////////////////////////////////////////////////////
// Constructor
MobileOperatorInfoImpl(EventDispatcher* dispatcher,
const std::string& info_owner,
const std::string& default_db_path,
const std::string& override_db_path);
// ///////////////////////////////////////////////////////////////////////////
// Static variables.
// Default databases to load.
static const char kDefaultDatabasePath[];
static const char kOverrideDatabasePath[];
// MCCMNC can be of length 5 or 6. When using this constant, keep in mind that
// the length of MCCMNC can by |kMCCMNCMinLen| or |kMCCMNCMinLen + 1|.
static const int kMCCMNCMinLen;
// ///////////////////////////////////////////////////////////////////////////
// Functions.
void PreprocessDatabase();
// This function assumes that duplicate |values| are never inserted for the
// same |key|. If you do that, the function is too dumb to deduplicate the
// |value|s, and two copies will get stored.
void InsertIntoStringToMNOListMap(
StringToMNOListMap* table,
const std::string& key,
const mobile_operator_db::MobileNetworkOperator* value);
bool UpdateMNO();
bool UpdateMVNO();
bool FilterMatches(const shill::mobile_operator_db::Filter& filter);
const mobile_operator_db::MobileNetworkOperator* PickOneFromDuplicates(
const std::vector<const mobile_operator_db::MobileNetworkOperator*>
&duplicates) const;
// Reloads the information about M[V]NO from the database.
void RefreshDBInformation();
void ClearDBInformation();
// Reload all data from |data|.
// Semantics: If a field data.x exists, then it *overwrites* the current
// information gained from data.x. E.g., if |data.name_size() > 0| is true,
// then we replace *all* names. Otherwise, we leave names untouched.
// This allows MVNOs to overwrite information obtained from the corresponding
// MNO.
void ReloadData(const mobile_operator_db::Data& data);
// Append candidates recognized by |mccmnc| to the candidate list.
bool AppendToCandidatesByMCCMNC(const std::string& mccmnc);
bool AppendToCandidatesBySID(const std::string& sid);
std::string OperatorCodeString() const;
// Notifies all observers that the operator has changed.
void PostNotifyOperatorChanged();
// The actual notification is sent out here. This should not be called
// directly from any function.
void NotifyOperatorChanged();
// For a property update that does not result in an M[V]NO update, this
// function determines whether observers should be notified anyway.
bool ShouldNotifyPropertyUpdate() const;
// OperatorName comparisons for determining the MNO are done after normalizing
// the names to ignore case and spaces.
std::string NormalizeOperatorName(const std::string& name) const;
// These functions encapsulate the logic to update different properties
// properly whenever an update is either received from the user or the
// database.
void HandleMCCMNCUpdate();
void HandleOperatorNameUpdate();
void HandleSIDUpdate();
void HandleOnlinePortalUpdate();
// Accessor functions for testing purpose only.
mobile_operator_db::MobileOperatorDB* database() {
return database_.get();
// ///////////////////////////////////////////////////////////////////////////
// Data.
// Not owned by MobileOperatorInfoImpl.
EventDispatcher* const dispatcher_;
const std::string info_owner_;
// Owned by MobileOperatorInfoImpl, may be created externally.
std::vector<base::FilePath> database_paths_;
// Owned and modified only by MobileOperatorInfoImpl.
// The observers added to this list are not owned by this object. Moreover,
// the observer is likely to outlive this object. We do enforce removal of all
// observers before this object is destroyed.
base::ObserverList<MobileOperatorInfo::Observer> observers_;
base::CancelableClosure notify_operator_changed_task_;
std::unique_ptr<mobile_operator_db::MobileOperatorDB> database_;
StringToMNOListMap mccmnc_to_mnos_;
StringToMNOListMap sid_to_mnos_;
StringToMNOListMap name_to_mnos_;
// |candidates_by_operator_code| can be determined either using MCCMNC or
// using SID. At any one time, we only expect one of these operator codes to
// be updated by the user. We use |operator_code_type_| to keep track of which
// update we have received and warn the user if we receive both.
enum OperatorCodeType {
kOperatorCodeTypeUnknown = 0,
OperatorCodeType operator_code_type_;
std::vector<const mobile_operator_db::MobileNetworkOperator*>
std::vector<const mobile_operator_db::MobileNetworkOperator*>
const mobile_operator_db::MobileNetworkOperator* current_mno_;
const mobile_operator_db::MobileVirtualNetworkOperator* current_mvno_;
// These fields are the information expected to be populated by this object
// after successfully determining the MVNO.
std::string uuid_;
std::string operator_name_;
std::string country_;
std::string mccmnc_;
std::string sid_;
std::string nid_;
std::vector<std::string> mccmnc_list_;
std::vector<std::string> sid_list_;
std::vector<MobileOperatorInfo::LocalizedName> operator_name_list_;
std::vector<std::unique_ptr<MobileOperatorInfo::MobileAPN>> apn_list_;
std::vector<MobileOperatorInfo::OnlinePortal> olp_list_;
std::vector<mobile_operator_db::OnlinePortal> raw_olp_list_;
std::string activation_code_;
bool requires_roaming_;
// These fields store the data obtained from the Update* methods.
// The database information is kept separate from the information gathered
// through the Update* methods, because one or the other may be given
// precedence in different situations.
// Note: For simplicity, we do not allow the user to enforce an empty value
// for these variables. So, if |user_mccmnc_| == "", the |mccmnc_| obtained
// from the database will be used, even if |user_mccmnc_| was explicitly set
// by the user.
std::string user_imsi_;
std::string user_iccid_;
std::string user_mccmnc_;
std::string user_sid_;
std::string user_nid_;
std::string user_operator_name_;
bool user_olp_empty_;
MobileOperatorInfo::OnlinePortal user_olp_;
// This must be the last data member of this class.
base::WeakPtrFactory<MobileOperatorInfoImpl> weak_ptr_factory_;
} // namespace shill