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