/* * 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