1 /* 2 * Copyright (C) 2017 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 package android.car.vms; 18 19 import android.annotation.SystemApi; 20 import android.util.Log; 21 import android.util.Slog; 22 23 import com.android.internal.annotations.VisibleForTesting; 24 25 import org.json.JSONArray; 26 import org.json.JSONException; 27 import org.json.JSONObject; 28 29 /** 30 * Records VMS operations using the Android Log. 31 * 32 * This class records VMS operations. The recorded messages include the VMS operations and its 33 * arguments encoded as JSON text so that the string can be both read as a log message and easily 34 * parsed. VmsOperationRecorder is intended to be called after successful state change. 35 * 36 * Access the VmsOperationRecorder using the {@link #get()} method, which returns a singleton 37 * instance. Each VMS operation has a corresponding VmsOperationRecorder method. For instance: 38 * <pre>{@code 39 * VmsOperationRecorder.get().subscribe(layer); 40 * }</pre> 41 * 42 * @deprecated VmsOperationRecorder is no longer used by VMS and will produce no output 43 * @hide 44 */ 45 @Deprecated 46 @SystemApi 47 public final class VmsOperationRecorder { 48 private static final String TAG = "VmsOperationRecorder"; 49 private static final VmsOperationRecorder INSTANCE = new VmsOperationRecorder(new Writer()); 50 private final Writer mWriter; 51 52 /** @hide */ 53 @VisibleForTesting VmsOperationRecorder(Writer writer)54 public VmsOperationRecorder(Writer writer) { 55 mWriter = writer; 56 } 57 58 /** Return the singleton instance. */ get()59 public static VmsOperationRecorder get() { 60 return INSTANCE; 61 } 62 63 // VMS Client operations. 64 65 /** 66 * Records {@code subscribe} operation with the {@link VmsLayer} layer passed as parameter. 67 */ subscribe(VmsLayer layer)68 public void subscribe(VmsLayer layer) { 69 recordOp("subscribe", layer); 70 } 71 72 /** 73 * Records {@code unsubscribe} operation with the {@link VmsLayer} layer passed as parameter. 74 */ unsubscribe(VmsLayer layer)75 public void unsubscribe(VmsLayer layer) { 76 recordOp("unsubscribe", layer); 77 } 78 79 /** 80 * Records {@code subscribe} operation with the {@link VmsLayer} layer and publisher id passed 81 * both as parameter. 82 */ subscribe(VmsLayer layer, int publisherId)83 public void subscribe(VmsLayer layer, int publisherId) { 84 recordOp("subscribe", "publisherId", publisherId, layer); 85 } 86 87 /** 88 * Record {@code unsubscribe} operation with the {@link VmsLayer} layer and publisher id passed 89 * both as parameter. 90 */ unsubscribe(VmsLayer layer, int publisherId)91 public void unsubscribe(VmsLayer layer, int publisherId) { 92 recordOp("unsubscribe", "publisherId", publisherId, layer); 93 } 94 95 /** 96 * Records {@code startMonitoring} operation. 97 */ startMonitoring()98 public void startMonitoring() { 99 recordOp("startMonitoring"); 100 } 101 102 /** 103 * Records {@code stopMonitoring} operation. 104 */ stopMonitoring()105 public void stopMonitoring() { 106 recordOp("stopMonitoring"); 107 } 108 109 /** 110 * Records {@code setLayerOffering} operation with the {@link VmsLayerOffering} offering 111 * passed as parameter. 112 */ setLayersOffering(VmsLayersOffering layersOffering)113 public void setLayersOffering(VmsLayersOffering layersOffering) { 114 recordOp("setLayersOffering", layersOffering); 115 } 116 117 /** 118 * Records {@code getPublisherId} operation with the publisher id passed as parameter. 119 */ getPublisherId(int publisherId)120 public void getPublisherId(int publisherId) { 121 recordOp("getPublisherId", "publisherId", publisherId); 122 } 123 124 // VMS Service operations. 125 126 /** 127 * Records {@code addSubscription} operation with the {@link VmsLayer} and the sequenceNumber 128 * passed as parameter. 129 */ addSubscription(int sequenceNumber, VmsLayer layer)130 public void addSubscription(int sequenceNumber, VmsLayer layer) { 131 recordOp("addSubscription", "sequenceNumber", sequenceNumber, layer); 132 } 133 134 /** 135 * Records {@code addPromiscuousSubscription} operation with the {@link VmsLayer} and the 136 * sequenceNumber passed as parameter. 137 */ removeSubscription(int sequenceNumber, VmsLayer layer)138 public void removeSubscription(int sequenceNumber, VmsLayer layer) { 139 recordOp("removeSubscription", "sequenceNumber", sequenceNumber, layer); 140 } 141 142 /** 143 * Records {@code addPromiscuousSubscription} operation with the sequenceNumber passed as 144 * parameter. 145 */ addPromiscuousSubscription(int sequenceNumber)146 public void addPromiscuousSubscription(int sequenceNumber) { 147 recordOp("addPromiscuousSubscription", "sequenceNumber", sequenceNumber); 148 } 149 150 /** 151 * Records {@code removePromiscuousSubscription} operation with the sequenceNumber passed as 152 * parameter. 153 */ removePromiscuousSubscription(int sequenceNumber)154 public void removePromiscuousSubscription(int sequenceNumber) { 155 recordOp("removePromiscuousSubscription", "sequenceNumber", sequenceNumber); 156 } 157 158 /** 159 * Records {@code addHalSubscription} operation with the {@link VmsLayer} layer and 160 * sequenceNumber both passed as parameter. 161 */ addHalSubscription(int sequenceNumber, VmsLayer layer)162 public void addHalSubscription(int sequenceNumber, VmsLayer layer) { 163 recordOp("addHalSubscription", "sequenceNumber", sequenceNumber, layer); 164 } 165 166 /** 167 * Records {@code removeHalSubscription} operation with the {@link VmsLayer} layer and 168 * sequenceNumber both passed as parameter. 169 */ removeHalSubscription(int sequenceNumber, VmsLayer layer)170 public void removeHalSubscription(int sequenceNumber, VmsLayer layer) { 171 recordOp("removeHalSubscription", "sequenceNumber", sequenceNumber, layer); 172 } 173 174 /** 175 * Records {@code setPublisherLayersOffering} operation with the {@link VmsLayersOffering} 176 * layersOffering passed as parameter. 177 */ setPublisherLayersOffering(VmsLayersOffering layersOffering)178 public void setPublisherLayersOffering(VmsLayersOffering layersOffering) { 179 recordOp("setPublisherLayersOffering", layersOffering); 180 } 181 182 /** 183 * Records {@code setHalPublisherLayersOffering} operation with the {@link VmsLayersOffering} 184 * layersOffering passed as parameter. 185 */ setHalPublisherLayersOffering(VmsLayersOffering layersOffering)186 public void setHalPublisherLayersOffering(VmsLayersOffering layersOffering) { 187 recordOp("setHalPublisherLayersOffering", layersOffering); 188 } 189 recordOp(String operation)190 private void recordOp(String operation) { 191 if (isEnabled()) { 192 try { 193 write(new JSONObject().put(operation, new JSONObject())); 194 } catch (JSONException e) { 195 Slog.e(TAG, e.toString()); 196 } 197 } 198 } 199 recordOp(String operation, VmsLayer layer)200 private void recordOp(String operation, VmsLayer layer) { 201 if (isEnabled()) { 202 try { 203 recordOp(operation, new JSONObject().put("layer", toJson(layer))); 204 } catch (JSONException e) { 205 Slog.e(TAG, e.toString()); 206 } 207 } 208 } 209 recordOp(String operation, VmsLayersOffering layersOffering)210 private void recordOp(String operation, VmsLayersOffering layersOffering) { 211 if (isEnabled()) { 212 try { 213 JSONObject args = new JSONObject(); 214 args.put("publisherId", layersOffering.getPublisherId()); 215 JSONArray offering = toJson(layersOffering); 216 if (offering.length() > 0) { 217 args.put("layerDependency", offering); 218 } 219 recordOp(operation, args); 220 } catch (JSONException e) { 221 Slog.e(TAG, e.toString()); 222 } 223 } 224 } 225 recordOp(String operation, String intArgName, int arg)226 private void recordOp(String operation, String intArgName, int arg) { 227 if (isEnabled()) { 228 try { 229 recordOp(operation, new JSONObject().put(intArgName, arg)); 230 } catch (JSONException e) { 231 Slog.e(TAG, e.toString()); 232 } 233 } 234 } 235 recordOp(String operation, String intArgName, int arg, VmsLayer layer)236 private void recordOp(String operation, String intArgName, int arg, VmsLayer layer) { 237 if (isEnabled()) { 238 try { 239 recordOp(operation, 240 new JSONObject().put(intArgName, arg).put("layer", toJson(layer))); 241 } catch (JSONException e) { 242 Slog.e(TAG, e.toString()); 243 } 244 } 245 } 246 recordOp(String operation, JSONObject args)247 private void recordOp(String operation, JSONObject args) { 248 if (isEnabled()) { 249 try { 250 write(new JSONObject().put(operation, args)); 251 } catch (JSONException e) { 252 Slog.e(TAG, e.toString()); 253 } 254 } 255 } 256 toJson(VmsLayer layer)257 private static JSONObject toJson(VmsLayer layer) throws JSONException { 258 return new JSONObject() 259 .put("type", layer.getType()) 260 .put("subtype", layer.getSubtype()) 261 .put("version", layer.getVersion()); 262 } 263 toJson(VmsLayerDependency layerDependency)264 private static JSONObject toJson(VmsLayerDependency layerDependency) throws JSONException { 265 JSONObject dep = new JSONObject(); 266 dep.put("layer", toJson(layerDependency.getLayer())); 267 if (!layerDependency.getDependencies().isEmpty()) { 268 JSONArray dependencies = new JSONArray(); 269 for (VmsLayer dependency : layerDependency.getDependencies()) { 270 dependencies.put(toJson(dependency)); 271 } 272 dep.put("dependency", dependencies); 273 } 274 return dep; 275 } 276 toJson(VmsLayersOffering layersOffering)277 private static JSONArray toJson(VmsLayersOffering layersOffering) throws JSONException { 278 JSONArray offerings = new JSONArray(); 279 for (VmsLayerDependency layerDependency : layersOffering.getDependencies()) { 280 offerings.put(toJson(layerDependency)); 281 } 282 return offerings; 283 } 284 isEnabled()285 private boolean isEnabled() { 286 return mWriter.isEnabled(); 287 } 288 write(JSONObject object)289 private void write(JSONObject object) { 290 mWriter.write(object.toString()); 291 } 292 293 /** @hide */ 294 @VisibleForTesting 295 public static class Writer { 296 private static final String TAG = "VMS.RECORD.EVENT"; 297 private static final int LEVEL = Log.DEBUG; 298 isEnabled()299 public boolean isEnabled() { 300 return Log.isLoggable(TAG, LEVEL); 301 } 302 303 /** Logs the message passed as parameter. */ write(String msg)304 public void write(String msg) { 305 Log.println(LEVEL, TAG, msg); 306 } 307 } 308 } 309