18c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh/*
28c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh**
38c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh** Copyright 2015, The Android Open Source Project
48c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh**
58c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh** Licensed under the Apache License, Version 2.0 (the "License");
68c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh** you may not use this file except in compliance with the License.
78c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh** You may obtain a copy of the License at
88c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh**
98c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh**     http://www.apache.org/licenses/LICENSE-2.0
108c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh**
118c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh** Unless required by applicable law or agreed to in writing, software
128c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh** distributed under the License is distributed on an "AS IS" BASIS,
138c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh** See the License for the specific language governing permissions and
158c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh** limitations under the License.
168c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh*/
178c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
188c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh#include <stdio.h>
198c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh#include <stdlib.h>
208c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh#include <sstream>
218c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2266dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/file.h>
238c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
248c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh#include "configreader.h"
258c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh#include "perfprofdutils.h"
268c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
278c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh//
288c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// Config file path
298c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh//
308c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshstatic const char *config_file_path =
318c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    "/data/data/com.google.android.gms/files/perfprofd.conf";
328c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
338c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshConfigReader::ConfigReader()
348c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    : trace_config_read(false)
358c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
368c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addDefaultEntries();
378c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
388c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
398c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshConfigReader::~ConfigReader()
408c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
418c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
428c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
438c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshconst char *ConfigReader::getConfigFilePath()
448c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
458c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  return config_file_path;
468c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
478c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
488c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshvoid ConfigReader::setConfigFilePath(const char *path)
498c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
508c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  config_file_path = strdup(path);
518c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  W_ALOGI("config file path set to %s", config_file_path);
528c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
538c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
548c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh//
558c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// Populate the reader with the set of allowable entries
568c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh//
578c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshvoid ConfigReader::addDefaultEntries()
588c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
598c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Average number of seconds between perf profile collections (if
608c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // set to 100, then over time we want to see a perf profile
618c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // collected every 100 seconds). The actual time within the interval
628c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // for the collection is chosen randomly.
638c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("collection_interval", 14400, 100, UINT32_MAX);
648c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
658c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Use the specified fixed seed for random number generation (unit
668c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // testing)
678c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("use_fixed_seed", 0, 0, UINT32_MAX);
688c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
698c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // For testing purposes, number of times to iterate through main
708c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // loop.  Value of zero indicates that we should loop forever.
718c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("main_loop_iterations", 0, 0, UINT32_MAX);
728c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
738c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Destination directory (where to write profiles). This location
748c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // chosen since it is accessible to the uploader service.
758c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addStringEntry("destination_directory", "/data/misc/perfprofd");
768c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
778c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Config directory (where to read configs).
788c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addStringEntry("config_directory", "/data/data/com.google.android.gms/files");
798c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
808c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Full path to 'perf' executable.
818c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addStringEntry("perf_path", "/system/xbin/simpleperf");
828c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
838c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Desired sampling period (passed to perf -c option). Small
848c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // sampling periods can perturb the collected profiles, so enforce
858c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // min/max.
868c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("sampling_period", 500000, 5000, UINT32_MAX);
878c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
888c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Length of time to collect samples (number of seconds for 'perf
898c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // record -a' run).
908c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("sample_duration", 3, 2, 600);
918c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
928c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // If this parameter is non-zero it will cause perfprofd to
938c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // exit immediately if the build type is not userdebug or eng.
948c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Currently defaults to 1 (true).
958c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("only_debug_build", 1, 0, 1);
968c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
978c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // If the "mpdecision" service is running at the point we are ready
988c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // to kick off a profiling run, then temporarily disable the service
998c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // and hard-wire all cores on prior to the collection run, provided
1008c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // that the duration of the recording is less than or equal to the value of
1018c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // 'hardwire_cpus_max_duration'.
1028c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("hardwire_cpus", 1, 0, 1);
1038c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("hardwire_cpus_max_duration", 5, 1, UINT32_MAX);
1048c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1058c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Maximum number of unprocessed profiles we can accumulate in the
1068c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // destination directory. Once we reach this limit, we continue
1078c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // to collect, but we just overwrite the most recent profile.
1088c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("max_unprocessed_profiles", 10, 1, UINT32_MAX);
1098c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1108c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // If set to 1, pass the -g option when invoking 'perf' (requests
1118c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // stack traces as opposed to flat profile).
1128c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("stack_profile", 0, 0, 1);
1138c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1148c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // For unit testing only: if set to 1, emit info messages on config
1158c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // file parsing.
1168c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("trace_config_read", 0, 0, 1);
1178c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1188c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  // Control collection of various additional profile tags
1198c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("collect_cpu_utilization", 1, 0, 1);
1208c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("collect_charging_state", 1, 0, 1);
1218c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("collect_booting", 1, 0, 1);
1228c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  addUnsignedEntry("collect_camera_active", 0, 0, 1);
1238c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
1248c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1258c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshvoid ConfigReader::addUnsignedEntry(const char *key,
1268c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh                                    unsigned default_value,
1278c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh                                    unsigned min_value,
1288c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh                                    unsigned max_value)
1298c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
1308c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  std::string ks(key);
1318c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  if (u_entries.find(ks) != u_entries.end() ||
1328c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      s_entries.find(ks) != s_entries.end()) {
1338c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    W_ALOGE("internal error -- duplicate entry for key %s", key);
1348c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    exit(9);
1358c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  }
1368c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  values vals;
1378c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  vals.minv = min_value;
1388c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  vals.maxv = max_value;
1398c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  u_info[ks] = vals;
1408c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  u_entries[ks] = default_value;
1418c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
1428c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1438c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshvoid ConfigReader::addStringEntry(const char *key, const char *default_value)
1448c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
1458c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  std::string ks(key);
1468c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  if (u_entries.find(ks) != u_entries.end() ||
1478c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      s_entries.find(ks) != s_entries.end()) {
1488c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    W_ALOGE("internal error -- duplicate entry for key %s", key);
1498c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    exit(9);
1508c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  }
1518c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  if (default_value == nullptr) {
1528c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    W_ALOGE("internal error -- bad default value for key %s", key);
1538c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    exit(9);
1548c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  }
1558c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  s_entries[ks] = std::string(default_value);
1568c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
1578c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1588c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshunsigned ConfigReader::getUnsignedValue(const char *key) const
1598c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
1608c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  std::string ks(key);
1618c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  auto it = u_entries.find(ks);
1628c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  assert(it != u_entries.end());
1638c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  return it->second;
1648c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
1658c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1668c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshstd::string ConfigReader::getStringValue(const char *key) const
1678c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
1688c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  std::string ks(key);
1698c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  auto it = s_entries.find(ks);
1708c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  assert(it != s_entries.end());
1718c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  return it->second;
1728c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
1738c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1748c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshvoid ConfigReader::overrideUnsignedEntry(const char *key, unsigned new_value)
1758c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
1768c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  std::string ks(key);
1778c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  auto it = u_entries.find(ks);
1788c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  assert(it != u_entries.end());
1798c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  values vals;
1808c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  auto iit = u_info.find(key);
1818c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  assert(iit != u_info.end());
1828c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  vals = iit->second;
1838c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  assert(new_value >= vals.minv && new_value <= vals.maxv);
1848c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  it->second = new_value;
1858c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  W_ALOGI("option %s overridden to %u", key, new_value);
1868c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
1878c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1888c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
1898c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh//
1908c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// Parse a key=value pair read from the config file. This will issue
1918c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// warnings or errors to the system logs if the line can't be
1928c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// interpreted properly.
1938c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh//
1948c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshvoid ConfigReader::parseLine(const char *key,
1958c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh                             const char *value,
1968c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh                             unsigned linecount)
1978c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
1988c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  assert(key);
1998c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  assert(value);
2008c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2018c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  auto uit = u_entries.find(key);
2028c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  if (uit != u_entries.end()) {
2038c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    unsigned uvalue = 0;
2048c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    if (isdigit(value[0]) == 0 || sscanf(value, "%u", &uvalue) != 1) {
2058c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      W_ALOGW("line %d: malformed unsigned value (ignored)", linecount);
2068c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    } else {
2078c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      values vals;
2088c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      auto iit = u_info.find(key);
2098c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      assert(iit != u_info.end());
2108c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      vals = iit->second;
2118c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      if (uvalue < vals.minv || uvalue > vals.maxv) {
2128c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh        W_ALOGW("line %d: specified value %u for '%s' "
2138c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh                "outside permitted range [%u %u] (ignored)",
2148c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh                linecount, uvalue, key, vals.minv, vals.maxv);
2158c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      } else {
2168c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh        if (trace_config_read) {
2178c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh          W_ALOGI("option %s set to %u", key, uvalue);
2188c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh        }
2198c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh        uit->second = uvalue;
2208c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      }
2218c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    }
2228c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    trace_config_read = (getUnsignedValue("trace_config_read") != 0);
2238c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    return;
2248c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  }
2258c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2268c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  auto sit = s_entries.find(key);
2278c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  if (sit != s_entries.end()) {
2288c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    if (trace_config_read) {
2298c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      W_ALOGI("option %s set to %s", key, value);
2308c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    }
2318c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    sit->second = std::string(value);
2328c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    return;
2338c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  }
2348c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2358c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  W_ALOGW("line %d: unknown option '%s' ignored", linecount, key);
2368c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
2378c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2388c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshstatic bool isblank(const std::string &line)
2398c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
2408c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  for (std::string::const_iterator it = line.begin(); it != line.end(); ++it)
2418c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  {
2428c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    if (isspace(*it) == 0) {
2438c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      return false;
2448c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    }
2458c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  }
2468c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  return true;
2478c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
2488c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2498c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshbool ConfigReader::readFile()
2508c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{
2518c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  std::string contents;
2528c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  if (! android::base::ReadFileToString(config_file_path, &contents)) {
2538c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    return false;
2548c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  }
2558c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2568c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  std::stringstream ss(contents);
2578c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  std::string line;
2588c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  for (unsigned linecount = 1;
2598c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh       std::getline(ss,line,'\n');
2608c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh       linecount += 1)
2618c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  {
2628c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2638c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    // comment line?
2648c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    if (line[0] == '#') {
2658c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      continue;
2668c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    }
2678c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2688c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    // blank line?
2698c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    if (isblank(line.c_str())) {
2708c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      continue;
2718c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    }
2728c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2738c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    // look for X=Y assignment
2748c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    auto efound = line.find('=');
2758c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    if (efound == std::string::npos) {
2768c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      W_ALOGW("line %d: line malformed (no '=' found)", linecount);
2778c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh      continue;
2788c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    }
2798c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2808c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    std::string key(line.substr(0, efound));
2818c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    std::string value(line.substr(efound+1, std::string::npos));
2828c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2838c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh    parseLine(key.c_str(), value.c_str(), linecount);
2848c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  }
2858c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh
2868c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh  return true;
2878c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}
288