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
Instance()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
Initialize()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
GetJSONObject() const84 const sp<JSONObject> CalibrationFile::GetJSONObject() const {
85 return json_root_;
86 }
87
SetSingleAxis(const char * key,int32_t value)88 bool CalibrationFile::SetSingleAxis(const char *key, int32_t value) {
89 json_root_->setInt32(key, value);
90 return true;
91 }
92
SetSingleAxis(const char * key,float value)93 bool CalibrationFile::SetSingleAxis(const char *key, float value) {
94 json_root_->setFloat(key, value);
95 return true;
96 }
97
SetTripleAxis(const char * key,int32_t x,int32_t y,int32_t z)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
SetFourAxis(const char * key,int32_t x,int32_t y,int32_t z,int32_t w)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
Save()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