blob: d369085ca045d80ea47b8966883d1e95e20ab4a5 [file] [log] [blame]
Rui Qiua3418982021-08-20 11:21:12 -07001/*
2 * Copyright (C) 2021 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
17package com.android.car.telemetry;
18
Rui Qiu9b9341c2021-08-25 10:39:04 -070019import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_ALREADY_EXISTS;
20import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_NONE;
21import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_UNKNOWN;
22import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_VERSION_TOO_OLD;
23
Rui Qiu4624bac2021-10-12 16:41:18 -070024import android.car.telemetry.MetricsConfigKey;
Rui Qiu9b9341c2021-08-25 10:39:04 -070025import android.util.ArrayMap;
Rui Qiu4e8a48e2021-11-09 17:14:26 -080026import android.util.AtomicFile;
Rui Qiua3418982021-08-20 11:21:12 -070027
28import com.android.car.CarLog;
29import com.android.internal.annotations.VisibleForTesting;
Zhomart Mukhamejanov4d99b1e2021-10-15 21:36:52 -070030import com.android.server.utils.Slogf;
Rui Qiua3418982021-08-20 11:21:12 -070031
32import java.io.File;
Rui Qiu4e8a48e2021-11-09 17:14:26 -080033import java.io.FileOutputStream;
Rui Qiua3418982021-08-20 11:21:12 -070034import java.io.IOException;
35import java.nio.file.Files;
Rui Qiu4624bac2021-10-12 16:41:18 -070036import java.nio.file.Paths;
Rui Qiua3418982021-08-20 11:21:12 -070037import java.util.ArrayList;
38import java.util.List;
Rui Qiu9b9341c2021-08-25 10:39:04 -070039import java.util.Map;
Rui Qiua3418982021-08-20 11:21:12 -070040
41/**
42 * This class is responsible for storing, retrieving, and deleting {@link
43 * TelemetryProto.MetricsConfig}. All of the methods are blocking so the class should only be
Rui Qiuac8b5ba2021-08-25 16:04:17 -070044 * accessed on the telemetry thread.
Rui Qiua3418982021-08-20 11:21:12 -070045 */
Rui Qiu3d3806b2021-09-22 11:42:45 -070046public class MetricsConfigStore {
Rui Qiua3418982021-08-20 11:21:12 -070047 @VisibleForTesting
48 static final String METRICS_CONFIG_DIR = "metrics_configs";
49
50 private final File mConfigDirectory;
Rui Qiu9b9341c2021-08-25 10:39:04 -070051 private Map<String, TelemetryProto.MetricsConfig> mActiveConfigs;
Rui Qiua3418982021-08-20 11:21:12 -070052
Rui Qiu3d3806b2021-09-22 11:42:45 -070053 public MetricsConfigStore(File rootDirectory) {
Rui Qiua3418982021-08-20 11:21:12 -070054 mConfigDirectory = new File(rootDirectory, METRICS_CONFIG_DIR);
55 mConfigDirectory.mkdirs();
Rui Qiu9b9341c2021-08-25 10:39:04 -070056 mActiveConfigs = new ArrayMap<>();
Rui Qiu9b9341c2021-08-25 10:39:04 -070057 // TODO(b/197336485): Add expiration date check for MetricsConfig
58 for (File file : mConfigDirectory.listFiles()) {
Rui Qiu4e8a48e2021-11-09 17:14:26 -080059 AtomicFile atomicFile = new AtomicFile(file);
Rui Qiu9b9341c2021-08-25 10:39:04 -070060 try {
Rui Qiu9b9341c2021-08-25 10:39:04 -070061 TelemetryProto.MetricsConfig config =
Rui Qiu4e8a48e2021-11-09 17:14:26 -080062 TelemetryProto.MetricsConfig.parseFrom(atomicFile.readFully());
Rui Qiu9b9341c2021-08-25 10:39:04 -070063 mActiveConfigs.put(config.getName(), config);
Rui Qiu9b9341c2021-08-25 10:39:04 -070064 } catch (IOException e) {
65 // TODO(b/197336655): record failure
Rui Qiu4e8a48e2021-11-09 17:14:26 -080066 atomicFile.delete();
Rui Qiu9b9341c2021-08-25 10:39:04 -070067 }
68 }
Rui Qiua3418982021-08-20 11:21:12 -070069 }
70
71 /**
72 * Returns all active {@link TelemetryProto.MetricsConfig} from disk.
73 */
Rui Qiu3d3806b2021-09-22 11:42:45 -070074 public List<TelemetryProto.MetricsConfig> getActiveMetricsConfigs() {
Rui Qiu9b9341c2021-08-25 10:39:04 -070075 return new ArrayList<>(mActiveConfigs.values());
Rui Qiua3418982021-08-20 11:21:12 -070076 }
77
78 /**
Rui Qiu4624bac2021-10-12 16:41:18 -070079 * Stores the MetricsConfig to disk if it is valid. It checks both config name and version for
80 * validity.
Rui Qiua3418982021-08-20 11:21:12 -070081 *
82 * @param metricsConfig the config to be persisted to disk.
Rui Qiu4624bac2021-10-12 16:41:18 -070083 * @return {@link android.car.telemetry.CarTelemetryManager.MetricsConfigError} status code.
Rui Qiua3418982021-08-20 11:21:12 -070084 */
Rui Qiu3d3806b2021-09-22 11:42:45 -070085 public int addMetricsConfig(TelemetryProto.MetricsConfig metricsConfig) {
Rui Qiu9b9341c2021-08-25 10:39:04 -070086 // TODO(b/197336485): Check expiration date for MetricsConfig
Rui Qiu4624bac2021-10-12 16:41:18 -070087 if (metricsConfig.getVersion() <= 0) {
Rui Qiu9b9341c2021-08-25 10:39:04 -070088 return ERROR_METRICS_CONFIG_VERSION_TOO_OLD;
Rui Qiu4624bac2021-10-12 16:41:18 -070089 }
90 if (mActiveConfigs.containsKey(metricsConfig.getName())) {
91 int currentVersion = mActiveConfigs.get(metricsConfig.getName()).getVersion();
92 if (currentVersion > metricsConfig.getVersion()) {
93 return ERROR_METRICS_CONFIG_VERSION_TOO_OLD;
94 } else if (currentVersion == metricsConfig.getVersion()) {
95 return ERROR_METRICS_CONFIG_ALREADY_EXISTS;
96 }
Rui Qiu9b9341c2021-08-25 10:39:04 -070097 }
Rui Qiuf721b132021-09-10 12:41:09 -070098 mActiveConfigs.put(metricsConfig.getName(), metricsConfig);
Rui Qiu4e8a48e2021-11-09 17:14:26 -080099 AtomicFile atomicFile = new AtomicFile(new File(mConfigDirectory, metricsConfig.getName()));
100 FileOutputStream fos = null;
Rui Qiua3418982021-08-20 11:21:12 -0700101 try {
Rui Qiu4e8a48e2021-11-09 17:14:26 -0800102 fos = atomicFile.startWrite();
103 fos.write(metricsConfig.toByteArray());
104 atomicFile.finishWrite(fos);
Rui Qiua3418982021-08-20 11:21:12 -0700105 } catch (IOException e) {
106 // TODO(b/197336655): record failure
Rui Qiu4e8a48e2021-11-09 17:14:26 -0800107 atomicFile.failWrite(fos);
Zhomart Mukhamejanov4d99b1e2021-10-15 21:36:52 -0700108 Slogf.w(CarLog.TAG_TELEMETRY, "Failed to write metrics config to disk", e);
Rui Qiu9b9341c2021-08-25 10:39:04 -0700109 return ERROR_METRICS_CONFIG_UNKNOWN;
Rui Qiua3418982021-08-20 11:21:12 -0700110 }
Rui Qiu9b9341c2021-08-25 10:39:04 -0700111 return ERROR_METRICS_CONFIG_NONE;
Rui Qiua3418982021-08-20 11:21:12 -0700112 }
113
Rui Qiu4624bac2021-10-12 16:41:18 -0700114 /**
115 * Deletes the MetricsConfig from disk.
116 *
117 * @param key the unique identifier of the metrics config that should be deleted.
118 * @return true for successful removal, false otherwise.
119 */
120 public boolean removeMetricsConfig(MetricsConfigKey key) {
121 String metricsConfigName = key.getName();
122 if (!mActiveConfigs.containsKey(key.getName())
123 || mActiveConfigs.get(key.getName()).getVersion() != key.getVersion()) {
124 return false; // no match found, nothing to remove
Rui Qiu9f80c7c2021-09-28 15:15:36 -0700125 }
Rui Qiu4624bac2021-10-12 16:41:18 -0700126 mActiveConfigs.remove(metricsConfigName);
127 try {
128 return Files.deleteIfExists(Paths.get(
129 mConfigDirectory.getAbsolutePath(), metricsConfigName));
130 } catch (IOException e) {
131 Slogf.w(CarLog.TAG_TELEMETRY, "Failed to remove MetricsConfig: " + key.getName(), e);
132 // TODO(b/197336655): record failure
133 }
134 return false;
Rui Qiua3418982021-08-20 11:21:12 -0700135 }
Rui Qiu9b9341c2021-08-25 10:39:04 -0700136
Rui Qiu3d3806b2021-09-22 11:42:45 -0700137 /** Deletes all MetricsConfigs from disk. */
Rui Qiu9f80c7c2021-09-28 15:15:36 -0700138 public void removeAllMetricsConfigs() {
Rui Qiuf721b132021-09-10 12:41:09 -0700139 mActiveConfigs.clear();
140 for (File file : mConfigDirectory.listFiles()) {
Rui Qiu9f80c7c2021-09-28 15:15:36 -0700141 if (!file.delete()) {
Zhomart Mukhamejanov4d99b1e2021-10-15 21:36:52 -0700142 Slogf.w(CarLog.TAG_TELEMETRY, "Failed to remove MetricsConfig: " + file.getName());
Rui Qiu9f80c7c2021-09-28 15:15:36 -0700143 }
Rui Qiuf721b132021-09-10 12:41:09 -0700144 }
Rui Qiu9b9341c2021-08-25 10:39:04 -0700145 }
Rui Qiua3418982021-08-20 11:21:12 -0700146}