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