| /* |
| * Copyright (C) 2016 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. |
| */ |
| |
| #include "calibrationfile.h" |
| |
| #include "file.h" |
| #include "log.h" |
| |
| namespace android { |
| |
| constexpr char kCalibrationFile[] = "/persist/sensorcal.json"; |
| |
| std::shared_ptr<CalibrationFile> CalibrationFile::instance_; |
| |
| std::shared_ptr<CalibrationFile> CalibrationFile::Instance() { |
| if (!CalibrationFile::instance_) { |
| auto inst = std::shared_ptr<CalibrationFile>(new CalibrationFile()); |
| if (inst->Initialize()) { |
| CalibrationFile::instance_ = inst; |
| } |
| } |
| |
| return CalibrationFile::instance_; |
| } |
| |
| bool CalibrationFile::Initialize() { |
| file_ = std::unique_ptr<File>(new File(kCalibrationFile, "rw")); |
| |
| status_t err = file_->initCheck(); |
| if (err != OK) { |
| LOGE("Couldn't open calibration file: %d (%s)", err, strerror(-err)); |
| return false; |
| } |
| |
| off64_t file_size = file_->seekTo(0, SEEK_END); |
| if (file_size > 0) { |
| auto file_data = std::vector<char>(file_size); |
| file_->seekTo(0, SEEK_SET); |
| ssize_t bytes_read = file_->read(file_data.data(), file_size); |
| if (bytes_read != file_size) { |
| LOGE("Read of configuration file returned %zd, expected %" PRIu64, |
| bytes_read, file_size); |
| return false; |
| } |
| |
| sp<JSONCompound> json = JSONCompound::Parse(file_data.data(), file_size); |
| if (json == nullptr || !json->isObject()) { |
| // If there's an existing file and we couldn't parse it, or it |
| // parsed to something unexpected, then we don't want to wipe out |
| // the file - the user needs to decide what to do, e.g. they can |
| // manually edit to fix corruption, or delete it, etc. |
| LOGE("Couldn't parse sensor calibration file (requires manual " |
| "resolution)"); |
| return false; |
| } else { |
| json_root_ = reinterpret_cast<JSONObject*>(json.get()); |
| LOGD("Parsed JSONObject from file:\n%s", |
| json_root_->toString().c_str()); |
| } |
| } |
| |
| // No errors, but there was no existing calibration data so construct a new |
| // object |
| if (json_root_ == nullptr) { |
| json_root_ = new JSONObject(); |
| } |
| |
| return true; |
| } |
| |
| const sp<JSONObject> CalibrationFile::GetJSONObject() const { |
| return json_root_; |
| } |
| |
| bool CalibrationFile::SetSingleAxis(const char *key, int32_t value) { |
| json_root_->setInt32(key, value); |
| return true; |
| } |
| |
| bool CalibrationFile::SetSingleAxis(const char *key, float value) { |
| json_root_->setFloat(key, value); |
| return true; |
| } |
| |
| bool CalibrationFile::SetTripleAxis(const char *key, int32_t x, int32_t y, |
| int32_t z) { |
| sp<JSONArray> json_array = new JSONArray(); |
| json_array->addInt32(x); |
| json_array->addInt32(y); |
| json_array->addInt32(z); |
| json_root_->setArray(key, json_array); |
| return true; |
| } |
| |
| bool CalibrationFile::SetFourAxis(const char *key, int32_t x, int32_t y, |
| int32_t z, int32_t w) { |
| sp<JSONArray> json_array = new JSONArray(); |
| json_array->addInt32(x); |
| json_array->addInt32(y); |
| json_array->addInt32(z); |
| json_array->addInt32(w); |
| json_root_->setArray(key, json_array); |
| return true; |
| } |
| |
| bool CalibrationFile::Save() { |
| AString json_str = json_root_->toString(); |
| LOGD("Saving JSONObject to file (%zd bytes):\n%s", json_str.size(), |
| json_str.c_str()); |
| file_->seekTo(0, SEEK_SET); |
| ssize_t bytes_written = file_->write(json_str.c_str(), json_str.size()); |
| if (bytes_written < 0 || static_cast<size_t>(bytes_written) != json_str.size()) { |
| LOGE("Write returned %zd, expected %zu", bytes_written, json_str.size()); |
| return false; |
| } |
| return true; |
| } |
| |
| } // namespace android |