Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2013 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/pending_activation_store.h"
     18 
     19 #include "shill/logging.h"
     20 #include "shill/store_factory.h"
     21 #include "shill/store_interface.h"
     22 
     23 using base::FilePath;
     24 using std::string;
     25 
     26 namespace shill {
     27 
     28 namespace Logging {
     29 static auto kModuleLogScope = ScopeLogger::kCellular;
     30 static string ObjectID(const PendingActivationStore* p) {
     31   return "(pending_activation_store)";
     32 }
     33 }
     34 
     35 const char PendingActivationStore::kIccidGroupId[] = "iccid_list";
     36 const char PendingActivationStore::kMeidGroupId[] = "meid_list";
     37 // We're keeping the old file name here for backwards compatibility.
     38 const char PendingActivationStore::kStorageFileName[] =
     39     "activating_iccid_store.profile";
     40 
     41 PendingActivationStore::PendingActivationStore() {}
     42 
     43 PendingActivationStore::~PendingActivationStore() {
     44   if (storage_.get())
     45     storage_->Flush();  // Make certain that everything is persisted.
     46 }
     47 
     48 namespace {
     49 
     50 string StateToString(PendingActivationStore::State state) {
     51   switch (state) {
     52     case PendingActivationStore::kStateUnknown:
     53       return "Unknown";
     54     case PendingActivationStore::kStatePending:
     55       return "Pending";
     56     case PendingActivationStore::kStateActivated:
     57       return "Activated";
     58     default:
     59       return "Invalid";
     60   }
     61 }
     62 
     63 string FormattedIdentifier(PendingActivationStore::IdentifierType type,
     64                            const string& identifier) {
     65   string label;
     66   switch (type) {
     67     case PendingActivationStore::kIdentifierICCID:
     68       label = "ICCID";
     69       break;
     70     case PendingActivationStore::kIdentifierMEID:
     71       label = "MEID";
     72       break;
     73     default:
     74       NOTREACHED();
     75   }
     76   return "[" + label + "=" + identifier + "]";
     77 }
     78 
     79 }  // namespace
     80 
     81 // static
     82 string PendingActivationStore::IdentifierTypeToGroupId(IdentifierType type) {
     83   switch (type) {
     84     case kIdentifierICCID:
     85       return kIccidGroupId;
     86     case kIdentifierMEID:
     87       return kMeidGroupId;
     88     default:
     89       SLOG(Cellular, nullptr, 2) << "Incorrect identifier type: " << type;
     90       return "";
     91   }
     92 }
     93 
     94 bool PendingActivationStore::InitStorage(const FilePath& storage_path) {
     95   // Close the current file.
     96   if (storage_.get()) {
     97     storage_->Flush();
     98     storage_.reset();  // KeyFileStore closes the file in its destructor.
     99   }
    100   if (storage_path.empty()) {
    101     LOG(ERROR) << "Empty storage directory path provided.";
    102     return false;
    103   }
    104   FilePath path = storage_path.Append(kStorageFileName);
    105   std::unique_ptr<StoreInterface> storage(
    106     StoreFactory::GetInstance()->CreateStore(path));
    107   bool already_exists = storage->IsNonEmpty();
    108   if (!storage->Open()) {
    109     LOG(ERROR) << "Failed to open file at '" << path.AsUTF8Unsafe()  << "'";
    110     if (already_exists)
    111       storage->MarkAsCorrupted();
    112     return false;
    113   }
    114   if (!already_exists)
    115     storage->SetHeader("Identifiers pending cellular activation.");
    116   storage_.reset(storage.release());
    117   return true;
    118 }
    119 
    120 PendingActivationStore::State PendingActivationStore::GetActivationState(
    121     IdentifierType type,
    122     const string& identifier) const {
    123   string formatted_identifier = FormattedIdentifier(type, identifier);
    124   SLOG(this, 2) << __func__ << ": " << formatted_identifier;
    125   if (!storage_.get()) {
    126     LOG(ERROR) << "Underlying storage not initialized.";
    127     return kStateUnknown;
    128   }
    129   int state = 0;
    130   if (!storage_->GetInt(IdentifierTypeToGroupId(type), identifier, &state)) {
    131     SLOG(this, 2) << "No entry exists for " << formatted_identifier;
    132     return kStateUnknown;
    133   }
    134   if (state <= 0 || state >= kStateMax) {
    135     SLOG(this, 2) << "State value read for " << formatted_identifier
    136                   << " is invalid.";
    137     return kStateUnknown;
    138   }
    139   return static_cast<State>(state);
    140 }
    141 
    142 bool PendingActivationStore::SetActivationState(
    143     IdentifierType type,
    144     const string& identifier,
    145     State state) {
    146   SLOG(this, 2) << __func__ << ": State=" << StateToString(state) << ", "
    147                 << FormattedIdentifier(type, identifier);
    148   if (!storage_.get()) {
    149     LOG(ERROR) << "Underlying storage not initialized.";
    150     return false;
    151   }
    152   if (state == kStateUnknown) {
    153     SLOG(this, 2) << "kStateUnknown cannot be used as a value.";
    154     return false;
    155   }
    156   if (state < 0 || state >= kStateMax) {
    157     SLOG(this, 2) << "Cannot set state to \"" << StateToString(state)
    158                   << "\"";
    159     return false;
    160   }
    161   if (!storage_->SetInt(
    162       IdentifierTypeToGroupId(type), identifier, static_cast<int>(state))) {
    163     SLOG(this, 2) << "Failed to store the given identifier and state "
    164                   << "values.";
    165     return false;
    166   }
    167   return storage_->Flush();
    168 }
    169 
    170 bool PendingActivationStore::RemoveEntry(IdentifierType type,
    171                                          const std::string& identifier) {
    172   SLOG(this, 2) << __func__ << ": "
    173                 << FormattedIdentifier(type, identifier);
    174   if (!storage_.get()) {
    175     LOG(ERROR) << "Underlying storage not initialized.";
    176     return false;
    177   }
    178   if (!storage_->DeleteKey(IdentifierTypeToGroupId(type), identifier)) {
    179     SLOG(this, 2) << "Failed to remove the given identifier.";
    180     return false;
    181   }
    182   return storage_->Flush();
    183 }
    184 
    185 }  // namespace shill
    186