1 /* 2 * Copyright (C) 2016 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 "calibrationfile.h" 18 19 #include "file.h" 20 #include "log.h" 21 22 namespace android { 23 24 constexpr char kCalibrationFile[] = "/persist/sensorcal.json"; 25 26 std::shared_ptr<CalibrationFile> CalibrationFile::instance_; 27 28 std::shared_ptr<CalibrationFile> CalibrationFile::Instance() { 29 if (!CalibrationFile::instance_) { 30 auto inst = std::shared_ptr<CalibrationFile>(new CalibrationFile()); 31 if (inst->Initialize()) { 32 CalibrationFile::instance_ = inst; 33 } 34 } 35 36 return CalibrationFile::instance_; 37 } 38 39 bool CalibrationFile::Initialize() { 40 file_ = std::unique_ptr<File>(new File(kCalibrationFile, "rw")); 41 42 status_t err = file_->initCheck(); 43 if (err != OK) { 44 LOGE("Couldn't open calibration file: %d (%s)", err, strerror(-err)); 45 return false; 46 } 47 48 off64_t file_size = file_->seekTo(0, SEEK_END); 49 if (file_size > 0) { 50 auto file_data = std::vector<char>(file_size); 51 file_->seekTo(0, SEEK_SET); 52 ssize_t bytes_read = file_->read(file_data.data(), file_size); 53 if (bytes_read != file_size) { 54 LOGE("Read of configuration file returned %zd, expected %" PRIu64, 55 bytes_read, file_size); 56 return false; 57 } 58 59 sp<JSONCompound> json = JSONCompound::Parse(file_data.data(), file_size); 60 if (json == nullptr || !json->isObject()) { 61 // If there's an existing file and we couldn't parse it, or it 62 // parsed to something unexpected, then we don't want to wipe out 63 // the file - the user needs to decide what to do, e.g. they can 64 // manually edit to fix corruption, or delete it, etc. 65 LOGE("Couldn't parse sensor calibration file (requires manual " 66 "resolution)"); 67 return false; 68 } else { 69 json_root_ = reinterpret_cast<JSONObject*>(json.get()); 70 LOGD("Parsed JSONObject from file:\n%s", 71 json_root_->toString().c_str()); 72 } 73 } 74 75 // No errors, but there was no existing calibration data so construct a new 76 // object 77 if (json_root_ == nullptr) { 78 json_root_ = new JSONObject(); 79 } 80 81 return true; 82 } 83 84 const sp<JSONObject> CalibrationFile::GetJSONObject() const { 85 return json_root_; 86 } 87 88 bool CalibrationFile::SetSingleAxis(const char *key, int32_t value) { 89 json_root_->setInt32(key, value); 90 return true; 91 } 92 93 bool CalibrationFile::SetSingleAxis(const char *key, float value) { 94 json_root_->setFloat(key, value); 95 return true; 96 } 97 98 bool CalibrationFile::SetTripleAxis(const char *key, int32_t x, int32_t y, 99 int32_t z) { 100 sp<JSONArray> json_array = new JSONArray(); 101 json_array->addInt32(x); 102 json_array->addInt32(y); 103 json_array->addInt32(z); 104 json_root_->setArray(key, json_array); 105 return true; 106 } 107 108 bool CalibrationFile::SetFourAxis(const char *key, int32_t x, int32_t y, 109 int32_t z, int32_t w) { 110 sp<JSONArray> json_array = new JSONArray(); 111 json_array->addInt32(x); 112 json_array->addInt32(y); 113 json_array->addInt32(z); 114 json_array->addInt32(w); 115 json_root_->setArray(key, json_array); 116 return true; 117 } 118 119 bool CalibrationFile::Save() { 120 AString json_str = json_root_->toString(); 121 LOGD("Saving JSONObject to file (%zd bytes):\n%s", json_str.size(), 122 json_str.c_str()); 123 file_->seekTo(0, SEEK_SET); 124 ssize_t bytes_written = file_->write(json_str.c_str(), json_str.size()); 125 if (bytes_written < 0 || static_cast<size_t>(bytes_written) != json_str.size()) { 126 LOGE("Write returned %zd, expected %zu", bytes_written, json_str.size()); 127 return false; 128 } 129 return true; 130 } 131 132 } // namespace android 133