Home | History | Annotate | Download | only in nanotool
      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