//
// 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
//
// 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.
//
#ifndef SHILL_CELLULAR_MOBILE_OPERATOR_INFO_IMPL_H_
#define SHILL_CELLULAR_MOBILE_OPERATOR_INFO_IMPL_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <base/cancelable_callback.h>
#include <base/files/file_util.h>
#include <base/memory/scoped_vector.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 {
public:
typedef
std::map<std::string,
std::vector<const mobile_operator_db::MobileNetworkOperator*>>
StringToMNOListMap;
MobileOperatorInfoImpl(EventDispatcher* dispatcher,
const std::string& info_owner);
~MobileOperatorInfoImpl();
// API functions of the interface.
// See mobile_operator_info_impl.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 ScopedVector<MobileOperatorInfo::MobileAPN>& apn_list() const;
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);
private:
friend class MobileOperatorInfoInitTest;
// ///////////////////////////////////////////////////////////////////////////
// Static variables.
// Default databases to load.
static const char* kDefaultDatabasePath;
// 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,
kOperatorCodeTypeMCCMNC,
kOperatorCodeTypeSID,
};
OperatorCodeType operator_code_type_;
std::vector<const mobile_operator_db::MobileNetworkOperator*>
candidates_by_operator_code_;
std::vector<const mobile_operator_db::MobileNetworkOperator*>
candidates_by_name_;
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_;
ScopedVector<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_;
DISALLOW_COPY_AND_ASSIGN(MobileOperatorInfoImpl);
};
} // namespace shill
#endif // SHILL_CELLULAR_MOBILE_OPERATOR_INFO_IMPL_H_