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;
ObjectID(const PendingActivationStore * p)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 
PendingActivationStore()41 PendingActivationStore::PendingActivationStore() {}
42 
~PendingActivationStore()43 PendingActivationStore::~PendingActivationStore() {
44   if (storage_.get())
45     storage_->Flush();  // Make certain that everything is persisted.
46 }
47 
48 namespace {
49 
StateToString(PendingActivationStore::State state)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 
FormattedIdentifier(PendingActivationStore::IdentifierType type,const string & identifier)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
IdentifierTypeToGroupId(IdentifierType type)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 
InitStorage(const FilePath & storage_path)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 
GetActivationState(IdentifierType type,const string & identifier) const120 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 
SetActivationState(IdentifierType type,const string & identifier,State state)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 
RemoveEntry(IdentifierType type,const std::string & identifier)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