1 /* 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 17 package com.google.android.car.kitchensink.telemetry; 18 19 import static android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.ACTIVITY_FOREGROUND_STATE_CHANGED; 20 import static android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.ANR_OCCURRED; 21 import static android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.APP_CRASH_OCCURRED; 22 import static android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.APP_START_MEMORY_STATE_CAPTURED; 23 import static android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.PROCESS_CPU_TIME; 24 import static android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.PROCESS_MEMORY_SNAPSHOT; 25 import static android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.PROCESS_MEMORY_STATE; 26 import static android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.PROCESS_START_TIME; 27 import static android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.WTF_OCCURRED; 28 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.annotation.RawRes; 32 import android.app.ActivityManager; 33 import android.car.VehiclePropertyIds; 34 import android.car.telemetry.CarTelemetryManager; 35 import android.car.telemetry.TelemetryProto; 36 import android.car.telemetry.TelemetryProto.ConnectivityPublisher; 37 import android.os.Bundle; 38 import android.os.PersistableBundle; 39 import android.util.Log; 40 import android.view.LayoutInflater; 41 import android.view.View; 42 import android.view.ViewGroup; 43 import android.widget.Button; 44 import android.widget.TextView; 45 46 import androidx.fragment.app.Fragment; 47 48 import com.google.android.car.kitchensink.KitchenSinkActivity; 49 import com.google.android.car.kitchensink.R; 50 import com.google.protobuf.InvalidProtocolBufferException; 51 52 import java.io.BufferedReader; 53 import java.io.File; 54 import java.io.IOException; 55 import java.io.InputStream; 56 import java.io.InputStreamReader; 57 import java.nio.file.Files; 58 import java.nio.file.Path; 59 import java.nio.file.Paths; 60 import java.time.LocalDateTime; 61 import java.time.format.DateTimeFormatter; 62 import java.util.concurrent.Executor; 63 import java.util.concurrent.Executors; 64 65 public class CarTelemetryTestFragment extends Fragment { 66 private static final String TAG = CarTelemetryTestFragment.class.getSimpleName(); 67 68 private static final int SCRIPT_EXECUTION_PRIORITY_HIGH = 0; 69 private static final int SCRIPT_EXECUTION_PRIORITY_LOW = 100; 70 71 /** Vehicle property via gear change section. */ 72 private static final String LUA_SCRIPT_ON_GEAR_CHANGE = 73 "function onGearChange(published_data, state)\n" 74 + " t = {}\n" 75 + " for k, v in ipairs(published_data) do\n" 76 + " t['#' .. k] = 'Gear: ' .. v['vp.intVal'] \n" 77 + " log(v[\"vp.intVal\"])\n" 78 + " end\n" 79 + " on_metrics_report(t)\n" 80 + "end\n"; 81 82 private static final TelemetryProto.Publisher VEHICLE_PROPERTY_PUBLISHER = 83 TelemetryProto.Publisher.newBuilder() 84 .setVehicleProperty( 85 TelemetryProto.VehiclePropertyPublisher.newBuilder() 86 .setVehiclePropertyId(VehiclePropertyIds.GEAR_SELECTION) 87 .setReadRate(0f) 88 .build()) 89 .build(); 90 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_ON_GEAR_CHANGE_V1 = 91 TelemetryProto.MetricsConfig.newBuilder() 92 .setName("my_metrics_config") 93 .setVersion(1) 94 .setScript(LUA_SCRIPT_ON_GEAR_CHANGE) 95 .addSubscribers( 96 TelemetryProto.Subscriber.newBuilder() 97 .setHandler("onGearChange") 98 .setPublisher(VEHICLE_PROPERTY_PUBLISHER) 99 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 100 .build(); 101 private static final String ON_GEAR_CHANGE_CONFIG_NAME = 102 METRICS_CONFIG_ON_GEAR_CHANGE_V1.getName(); 103 104 /** ProcessMemoryState section. */ 105 private static final String LUA_SCRIPT_ON_PROCESS_MEMORY_STATE = new StringBuilder() 106 .append("function calculateAverage(tbl)\n") 107 .append(" local sum = 0\n") 108 .append(" local size = 0\n") 109 .append(" for _, value in ipairs(tbl) do\n") 110 .append(" sum = sum + value\n") 111 .append(" size = size + 1\n") 112 .append(" end\n") 113 .append(" return sum/size\n") 114 .append("end\n") 115 .append("function onProcessMemory(published_data, state)\n") 116 .append(" local result = {}\n") 117 .append(" result.page_fault_avg = calculateAverage(" 118 + "published_data['stats.page_fault'])\n") 119 .append(" result.major_page_fault_avg = calculateAverage(" 120 + "published_data['stats.page_major_fault'])\n") 121 .append(" result.oom_adj_score_avg = calculateAverage(" 122 + "published_data['stats.oom_adj_score'])\n") 123 .append(" result.rss_in_bytes_avg = calculateAverage(" 124 + "published_data['stats.rss_in_bytes'])\n") 125 .append(" result.swap_in_bytes_avg = calculateAverage(" 126 + "published_data['stats.swap_in_bytes'])\n") 127 .append(" result.cache_in_bytes_avg = calculateAverage(" 128 + "published_data['stats.cache_in_bytes'])\n") 129 .append(" on_script_finished(result)\n") 130 .append("end\n") 131 .toString(); 132 private static final TelemetryProto.Publisher PROCESS_MEMORY_PUBLISHER = 133 TelemetryProto.Publisher.newBuilder() 134 .setStats( 135 TelemetryProto.StatsPublisher.newBuilder() 136 .setSystemMetric(PROCESS_MEMORY_STATE)) 137 .build(); 138 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_PROCESS_MEMORY_V1 = 139 TelemetryProto.MetricsConfig.newBuilder() 140 .setName("process_memory_metrics_config") 141 .setVersion(1) 142 .setScript(LUA_SCRIPT_ON_PROCESS_MEMORY_STATE) 143 .addSubscribers( 144 TelemetryProto.Subscriber.newBuilder() 145 .setHandler("onProcessMemory") 146 .setPublisher(PROCESS_MEMORY_PUBLISHER) 147 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 148 .build(); 149 private static final String PROCESS_MEMORY_CONFIG_NAME = 150 METRICS_CONFIG_PROCESS_MEMORY_V1.getName(); 151 152 /** AppStartMemoryStateCaptured section. */ 153 private static final String LUA_SCRIPT_ON_APP_START_MEMORY_STATE_CAPTURED = new StringBuilder() 154 .append("function calculateAverage(tbl)\n") 155 .append(" local sum = 0\n") 156 .append(" local size = 0\n") 157 .append(" for _, value in ipairs(tbl) do\n") 158 .append(" sum = sum + value\n") 159 .append(" size = size + 1\n") 160 .append(" end\n") 161 .append(" return sum/size\n") 162 .append("end\n") 163 .append("function onAppStartMemoryStateCaptured(published_data, state)\n") 164 .append(" local result = {}\n") 165 .append(" result.uid = published_data['stats.uid']\n") 166 .append(" result.page_fault_avg = calculateAverage(" 167 + "published_data['stats.page_fault'])\n") 168 .append(" result.major_page_fault_avg = calculateAverage(" 169 + "published_data['stats.page_major_fault'])\n") 170 .append(" result.rss_in_bytes_avg = calculateAverage(" 171 + "published_data['stats.rss_in_bytes'])\n") 172 .append(" result.swap_in_bytes_avg = calculateAverage(" 173 + "published_data['stats.swap_in_bytes'])\n") 174 .append(" result.cache_in_bytes_avg = calculateAverage(" 175 + "published_data['stats.cache_in_bytes'])\n") 176 .append(" on_script_finished(result)\n") 177 .append("end\n") 178 .toString(); 179 private static final TelemetryProto.Publisher APP_START_MEMORY_STATE_CAPTURED_PUBLISHER = 180 TelemetryProto.Publisher.newBuilder() 181 .setStats( 182 TelemetryProto.StatsPublisher.newBuilder() 183 .setSystemMetric(APP_START_MEMORY_STATE_CAPTURED)) 184 .build(); 185 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_APP_START_MEMORY_V1 = 186 TelemetryProto.MetricsConfig.newBuilder() 187 .setName("app_start_memory_metrics_config") 188 .setVersion(1) 189 .setScript(LUA_SCRIPT_ON_APP_START_MEMORY_STATE_CAPTURED) 190 .addSubscribers( 191 TelemetryProto.Subscriber.newBuilder() 192 .setHandler("onAppStartMemoryStateCaptured") 193 .setPublisher(APP_START_MEMORY_STATE_CAPTURED_PUBLISHER) 194 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 195 .build(); 196 private static final String APP_START_MEMORY_STATE_CAPTURED_CONFIG_NAME = 197 METRICS_CONFIG_APP_START_MEMORY_V1.getName(); 198 199 /** ActivityForegroundStateChanged section. */ 200 private static final String LUA_SCRIPT_ON_ACTIVITY_FOREGROUND_STATE_CHANGED = 201 new StringBuilder() 202 .append("function onActivityForegroundStateChanged(published_data, state)\n") 203 .append(" local result = {}\n") 204 .append(" local n = 0\n") 205 .append(" for k, v in pairs(published_data) do\n") 206 .append(" result[k] = v[1]\n") 207 .append(" n = n + 1\n") 208 .append(" end\n") 209 .append(" result.n = n\n") 210 .append(" on_script_finished(result)\n") 211 .append("end\n") 212 .toString(); 213 214 private static final TelemetryProto.Publisher ACTIVITY_FOREGROUND_STATE_CHANGED_PUBLISHER = 215 TelemetryProto.Publisher.newBuilder() 216 .setStats( 217 TelemetryProto.StatsPublisher.newBuilder() 218 .setSystemMetric(ACTIVITY_FOREGROUND_STATE_CHANGED)) 219 .build(); 220 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_ACTIVITY_FOREGROUND_STATE_V1 = 221 TelemetryProto.MetricsConfig.newBuilder() 222 .setName("activity_foreground_state_changed_config") 223 .setVersion(1) 224 .setScript(LUA_SCRIPT_ON_ACTIVITY_FOREGROUND_STATE_CHANGED) 225 .addSubscribers( 226 TelemetryProto.Subscriber.newBuilder() 227 .setHandler("onActivityForegroundStateChanged") 228 .setPublisher(ACTIVITY_FOREGROUND_STATE_CHANGED_PUBLISHER) 229 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 230 .build(); 231 private static final String ACTIVITY_FOREGROUND_STATE_CHANGED_CONFIG_NAME = 232 METRICS_CONFIG_ACTIVITY_FOREGROUND_STATE_V1.getName(); 233 234 /** ProcessCpuTime section */ 235 private static final String LUA_SCRIPT_ON_PROCESS_CPU_TIME = 236 new StringBuilder() 237 .append("function onProcessCpuTime(published_data, state)\n") 238 .append(" local result = {}\n") 239 .append(" local n = 0\n") 240 .append(" for k, v in pairs(published_data) do\n") 241 .append(" result[k] = v[1]\n") 242 .append(" n = n + 1\n") 243 .append(" end\n") 244 .append(" result.n = n\n") 245 .append(" on_script_finished(result)\n") 246 .append("end\n") 247 .toString(); 248 249 private static final TelemetryProto.Publisher PROCESS_CPU_TIME_PUBLISHER = 250 TelemetryProto.Publisher.newBuilder() 251 .setStats( 252 TelemetryProto.StatsPublisher.newBuilder() 253 .setSystemMetric(PROCESS_CPU_TIME)) 254 .build(); 255 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_PROCESS_CPU_TIME_V1 = 256 TelemetryProto.MetricsConfig.newBuilder() 257 .setName("process_cpu_time_config") 258 .setVersion(1) 259 .setScript(LUA_SCRIPT_ON_PROCESS_CPU_TIME) 260 .addSubscribers( 261 TelemetryProto.Subscriber.newBuilder() 262 .setHandler("onProcessCpuTime") 263 .setPublisher(PROCESS_CPU_TIME_PUBLISHER) 264 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 265 .build(); 266 private static final String PROCESS_CPU_TIME_CONFIG_NAME = 267 METRICS_CONFIG_PROCESS_CPU_TIME_V1.getName(); 268 269 /** AppCrashOccurred section */ 270 private static final String LUA_SCRIPT_ON_APP_CRASH_OCCURRED = 271 new StringBuilder() 272 .append("function onAppCrashOccurred(published_data, state)\n") 273 .append(" local result = {}\n") 274 .append(" for k, v in pairs(published_data) do\n") 275 .append(" result[k] = v[1]\n") 276 .append(" end\n") 277 .append(" on_script_finished(result)\n") 278 .append("end\n") 279 .toString(); 280 281 private static final TelemetryProto.Publisher APP_CRASH_OCCURRED_PUBLISHER = 282 TelemetryProto.Publisher.newBuilder() 283 .setStats( 284 TelemetryProto.StatsPublisher.newBuilder() 285 .setSystemMetric(APP_CRASH_OCCURRED)) 286 .build(); 287 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_APP_CRASH_OCCURRED_V1 = 288 TelemetryProto.MetricsConfig.newBuilder() 289 .setName("app_crash_occurred_config") 290 .setVersion(1) 291 .setScript(LUA_SCRIPT_ON_APP_CRASH_OCCURRED) 292 .addSubscribers( 293 TelemetryProto.Subscriber.newBuilder() 294 .setHandler("onAppCrashOccurred") 295 .setPublisher(APP_CRASH_OCCURRED_PUBLISHER) 296 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 297 .build(); 298 private static final String APP_CRASH_OCCURRED_CONFIG_NAME = 299 METRICS_CONFIG_APP_CRASH_OCCURRED_V1.getName(); 300 301 /** ANROccurred section */ 302 private static final String LUA_SCRIPT_ON_ANR_OCCURRED = 303 new StringBuilder() 304 .append("function onAnrOccurred(published_data, state)\n") 305 .append(" local result = {}\n") 306 .append(" for k, v in pairs(published_data) do\n") 307 .append(" result[k] = v[1]\n") 308 .append(" end\n") 309 .append(" on_script_finished(result)\n") 310 .append("end\n") 311 .toString(); 312 313 private static final TelemetryProto.Publisher ANR_OCCURRED_PUBLISHER = 314 TelemetryProto.Publisher.newBuilder() 315 .setStats( 316 TelemetryProto.StatsPublisher.newBuilder() 317 .setSystemMetric(ANR_OCCURRED)) 318 .build(); 319 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_ANR_OCCURRED_V1 = 320 TelemetryProto.MetricsConfig.newBuilder() 321 .setName("anr_occurred_config") 322 .setVersion(1) 323 .setScript(LUA_SCRIPT_ON_ANR_OCCURRED) 324 .addSubscribers( 325 TelemetryProto.Subscriber.newBuilder() 326 .setHandler("onAnrOccurred") 327 .setPublisher(ANR_OCCURRED_PUBLISHER) 328 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 329 .build(); 330 private static final String ANR_OCCURRED_CONFIG_NAME = METRICS_CONFIG_ANR_OCCURRED_V1.getName(); 331 332 /** WTFOccurred section */ 333 private static final String LUA_SCRIPT_ON_WTF_OCCURRED = 334 new StringBuilder() 335 .append("function onWtfOccurred(published_data, state)\n") 336 .append(" local result = {}\n") 337 .append(" for k, v in pairs(published_data) do\n") 338 .append(" result[k] = v[1]\n") 339 .append(" end\n") 340 .append(" on_script_finished(result)\n") 341 .append("end\n") 342 .toString(); 343 344 private static final TelemetryProto.Publisher WTF_OCCURRED_PUBLISHER = 345 TelemetryProto.Publisher.newBuilder() 346 .setStats( 347 TelemetryProto.StatsPublisher.newBuilder() 348 .setSystemMetric(WTF_OCCURRED)) 349 .build(); 350 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_WTF_OCCURRED_V1 = 351 TelemetryProto.MetricsConfig.newBuilder() 352 .setName("wtf_occurred_config") 353 .setVersion(1) 354 .setScript(LUA_SCRIPT_ON_WTF_OCCURRED) 355 .addSubscribers( 356 TelemetryProto.Subscriber.newBuilder() 357 .setHandler("onWtfOccurred") 358 .setPublisher(WTF_OCCURRED_PUBLISHER) 359 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 360 .build(); 361 private static final String WTF_OCCURRED_CONFIG_NAME = METRICS_CONFIG_WTF_OCCURRED_V1.getName(); 362 363 private static final TelemetryProto.Publisher WIFI_NETSTATS_PUBLISHER = 364 TelemetryProto.Publisher.newBuilder() 365 .setConnectivity( 366 ConnectivityPublisher.newBuilder() 367 .setTransport(ConnectivityPublisher.Transport.TRANSPORT_WIFI) 368 .setOemType(ConnectivityPublisher.OemType.OEM_NONE)) 369 .build(); 370 // This config uses the script "R.raw.telemetry_stats_and_connectivity_script". 371 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_WIFI_TOP_CONSUMERS = 372 TelemetryProto.MetricsConfig.newBuilder() 373 .setName("wifi_top_consumers") 374 .setVersion(1) 375 .addSubscribers( 376 TelemetryProto.Subscriber.newBuilder() 377 .setHandler("onWifiNetstatsForTopConsumers") 378 .setPublisher(WIFI_NETSTATS_PUBLISHER) 379 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 380 .build(); 381 private static final String WIFI_TOP_CONSUMERS_CONFIG_NAME = 382 METRICS_CONFIG_WIFI_TOP_CONSUMERS.getName(); 383 384 // This config uses the script "R.raw.telemetry_driving_sessions_script". 385 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_DRIVING_SESSIONS = 386 TelemetryProto.MetricsConfig.newBuilder() 387 .setName("wifi_stats_with_driving_sessions") 388 .setVersion(1) 389 .addSubscribers( 390 TelemetryProto.Subscriber.newBuilder() 391 .setHandler("onWifiStatsForDrivingSessions") 392 .setPublisher(WIFI_NETSTATS_PUBLISHER) 393 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 394 .build(); 395 private static final String WIFI_STATS_DRIVING_SESSIONS_CONFIG_NAME = 396 METRICS_CONFIG_DRIVING_SESSIONS.getName(); 397 398 /** 399 * PROCESS_CPU_TIME + PROCESS_MEMORY + WIFI_NETSTATS section. Reuses the same publisher 400 * configuration that were defined above for PROCESS_CPU_TIME, PROCESS_MEMORY, and 401 * WIFI_NETSTATS. Its script is R.raw.telemetry_stats_and_connectivity_script which is loaded at 402 * runtime. The script produces a final report when it receives atoms PROCESS_MEMORY and 403 * PROCESS_CPU_TIME, and more than 5 pieces of data from connectivity publisher. 404 */ 405 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_STATS_AND_CONNECTIVITY_V1 = 406 TelemetryProto.MetricsConfig.newBuilder() 407 .setName("stats_and_connectivity_metrics_config") 408 .setVersion(1) 409 .addSubscribers( 410 TelemetryProto.Subscriber.newBuilder() 411 .setHandler("onProcessMemory") 412 .setPublisher(PROCESS_MEMORY_PUBLISHER) 413 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 414 .addSubscribers( 415 TelemetryProto.Subscriber.newBuilder() 416 .setHandler("onProcessCpuTime") 417 .setPublisher(PROCESS_CPU_TIME_PUBLISHER) 418 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 419 .addSubscribers( 420 TelemetryProto.Subscriber.newBuilder() 421 .setHandler("onWifiNetstats") 422 .setPublisher(WIFI_NETSTATS_PUBLISHER) 423 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 424 .build(); 425 426 private static final String STATS_AND_CONNECTIVITY_CONFIG_NAME = 427 METRICS_CONFIG_STATS_AND_CONNECTIVITY_V1.getName(); 428 429 /** MemoryPublisher section. */ 430 private static final String LUA_SCRIPT_ON_MEMORY = 431 new StringBuilder() 432 .append("function onMemory(published_data, state)\n") 433 .append(" local iterations = state['iterations']\n") 434 .append(" if iterations == nil then\n") 435 .append(" iterations = 0\n") 436 .append(" end\n") 437 .append(" state['iterations'] = iterations + 1\n") 438 .append(" local meminfo = published_data['mem.meminfo']\n") 439 .append(" local available_memory = string.match(meminfo, " 440 + "'.*MemAvailable:%s*(%d+).*')\n") 441 .append(" local mem_key = 'available_memory_' .. iterations\n") 442 .append(" published_data[mem_key] = available_memory\n") 443 .append(" published_data['mem.meminfo'] = nil\n") 444 .append(" on_metrics_report(published_data, state)\n") 445 .append("end\n") 446 .toString(); 447 private static final TelemetryProto.Publisher MEMORY_PUBLISHER = 448 TelemetryProto.Publisher.newBuilder() 449 .setMemory( 450 TelemetryProto.MemoryPublisher.newBuilder() 451 .setReadIntervalSec(3) 452 .setMaxSnapshots(3) 453 .setMaxPendingTasks(10) 454 .addPackageNames("com.android.car") 455 .addPackageNames("com.android.car.scriptexecutor") 456 .build()) 457 .build(); 458 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_MEMORY_V1 = 459 TelemetryProto.MetricsConfig.newBuilder() 460 .setName("memory_config") 461 .setVersion(1) 462 .setScript(LUA_SCRIPT_ON_MEMORY) 463 .addSubscribers( 464 TelemetryProto.Subscriber.newBuilder() 465 .setHandler("onMemory") 466 .setPublisher(MEMORY_PUBLISHER) 467 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 468 .build(); 469 private static final String MEMORY_CONFIG_NAME = 470 METRICS_CONFIG_MEMORY_V1.getName(); 471 472 /** ProcessMemorySnapshot section. */ 473 private static final String LUA_SCRIPT_ON_PROCESS_MEMORY_SNAPSHOT = new StringBuilder() 474 .append("function onProcessMemorySnapshot(published_data, state)\n") 475 .append(" on_script_finished(published_data)\n") 476 .append("end\n") 477 .toString(); 478 private static final TelemetryProto.Publisher PROCESS_MEMORY_SNAPSHOT_PUBLISHER = 479 TelemetryProto.Publisher.newBuilder() 480 .setStats( 481 TelemetryProto.StatsPublisher.newBuilder() 482 .setSystemMetric(PROCESS_MEMORY_SNAPSHOT)) 483 .build(); 484 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_PROCESS_MEMORY_SNAPSHOT_V1 = 485 TelemetryProto.MetricsConfig.newBuilder() 486 .setName("process_memory_snapshot_metrics_config") 487 .setVersion(1) 488 .setScript(LUA_SCRIPT_ON_PROCESS_MEMORY_SNAPSHOT) 489 .addSubscribers( 490 TelemetryProto.Subscriber.newBuilder() 491 .setHandler("onProcessMemorySnapshot") 492 .setPublisher(PROCESS_MEMORY_SNAPSHOT_PUBLISHER) 493 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 494 .build(); 495 private static final String PROCESS_MEMORY_SNAPSHOT_CONFIG_NAME = 496 METRICS_CONFIG_PROCESS_MEMORY_SNAPSHOT_V1.getName(); 497 498 /** ProcessStartTime section. */ 499 private static final String LUA_SCRIPT_ON_PROCESS_START_TIME = new StringBuilder() 500 .append("function onProcessStartTime(published_data, state)\n") 501 .append(" on_script_finished(published_data)\n") 502 .append("end\n") 503 .toString(); 504 private static final TelemetryProto.Publisher PROCESS_START_TIME_PUBLISHER = 505 TelemetryProto.Publisher.newBuilder() 506 .setStats( 507 TelemetryProto.StatsPublisher.newBuilder() 508 .setSystemMetric(PROCESS_START_TIME)) 509 .build(); 510 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_PROCESS_START_TIME_V1 = 511 TelemetryProto.MetricsConfig.newBuilder() 512 .setName("process_start_time_metrics_config") 513 .setVersion(1) 514 .setScript(LUA_SCRIPT_ON_PROCESS_START_TIME) 515 .addSubscribers( 516 TelemetryProto.Subscriber.newBuilder() 517 .setHandler("onProcessStartTime") 518 .setPublisher(PROCESS_START_TIME_PUBLISHER) 519 .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH)) 520 .build(); 521 private static final String PROCESS_START_TIME_CONFIG_NAME = 522 METRICS_CONFIG_PROCESS_START_TIME_V1.getName(); 523 524 private final Executor mExecutor = Executors.newSingleThreadExecutor(); 525 526 private boolean mReceiveReportNotification = false; 527 private CarTelemetryManager mCarTelemetryManager; 528 private FinishedReportListenerImpl mListener; 529 private AddMetricsConfigCallbackImpl mAddMetricsConfigCallback; 530 private KitchenSinkActivity mActivity; 531 private TextView mOutputTextView; 532 private Button mTootleConfigsBtn; 533 private Button mEnableReportNotificationButton; 534 private View mConfigButtonsView; // MetricsConfig buttons 535 536 @Override onCreate(@ullable Bundle savedInstanceState)537 public void onCreate(@Nullable Bundle savedInstanceState) { 538 mActivity = (KitchenSinkActivity) getActivity(); 539 mCarTelemetryManager = mActivity.getCarTelemetryManager(); 540 mListener = new FinishedReportListenerImpl(); 541 mAddMetricsConfigCallback = new AddMetricsConfigCallbackImpl(); 542 super.onCreate(savedInstanceState); 543 } 544 545 @Nullable 546 @Override onCreateView( @onNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)547 public View onCreateView( 548 @NonNull LayoutInflater inflater, 549 @Nullable ViewGroup container, 550 @Nullable Bundle savedInstanceState) { 551 View view = inflater.inflate(R.layout.car_telemetry_test, container, false); 552 mOutputTextView = view.findViewById(R.id.output_textview); 553 mConfigButtonsView = view.findViewById(R.id.metrics_config_buttons_view); 554 mTootleConfigsBtn = view.findViewById(R.id.toggle_metrics_configs_btn); 555 mTootleConfigsBtn.setOnClickListener(this::toggleMetricsConfigButtons); 556 mEnableReportNotificationButton = view.findViewById(R.id.enable_report_notification_btn); 557 mEnableReportNotificationButton.setOnClickListener(this::enableReportNotification); 558 mEnableReportNotificationButton.setText( 559 getString(R.string.receive_report_notification_text, mReceiveReportNotification)); 560 561 /** VehiclePropertyPublisher on_gear_change */ 562 view.findViewById(R.id.send_on_gear_change_config) 563 .setOnClickListener(this::onSendGearChangeConfigBtnClick); 564 view.findViewById(R.id.remove_on_gear_change_config) 565 .setOnClickListener(this::onRemoveGearChangeConfigBtnClick); 566 view.findViewById(R.id.get_on_gear_change_report) 567 .setOnClickListener(this::onGetGearChangeReportBtnClick); 568 /** StatsPublisher process_memory */ 569 view.findViewById(R.id.send_on_process_memory_config) 570 .setOnClickListener(this::onSendProcessMemoryConfigBtnClick); 571 view.findViewById(R.id.remove_on_process_memory_config) 572 .setOnClickListener(this::onRemoveProcessMemoryConfigBtnClick); 573 view.findViewById(R.id.get_on_process_memory_report) 574 .setOnClickListener(this::onGetProcessMemoryReportBtnClick); 575 /** StatsPublisher app_start_memory_state */ 576 view.findViewById(R.id.send_on_app_start_memory_state_captured_config) 577 .setOnClickListener(this::onSendAppStartMemoryStateCapturedConfigBtnClick); 578 view.findViewById(R.id.remove_on_app_start_memory_state_captured_config) 579 .setOnClickListener(this::onRemoveAppStartMemoryStateCapturedConfigBtnClick); 580 view.findViewById(R.id.get_on_app_start_memory_state_captured_report) 581 .setOnClickListener(this::onGetAppStartMemoryStateCapturedReportBtnClick); 582 /** StatsPublisher activity_foreground_state_change */ 583 view.findViewById(R.id.send_on_activity_foreground_state_changed_config) 584 .setOnClickListener(this::onSendActivityForegroundStateChangedConfigBtnClick); 585 view.findViewById(R.id.remove_on_activity_foreground_state_changed_config) 586 .setOnClickListener(this::onRemoveActivityForegroundStateChangedConfigBtnClick); 587 view.findViewById(R.id.get_on_activity_foreground_state_changed_report) 588 .setOnClickListener(this::onGetActivityForegroundStateChangedReportBtnClick); 589 /** StatsPublisher process_cpu_time */ 590 view.findViewById(R.id.send_on_process_cpu_time_config) 591 .setOnClickListener(this::onSendProcessCpuTimeConfigBtnClick); 592 view.findViewById(R.id.remove_on_process_cpu_time_config) 593 .setOnClickListener(this::onRemoveProcessCpuTimeConfigBtnClick); 594 view.findViewById(R.id.get_on_process_cpu_time_report) 595 .setOnClickListener(this::onGetProcessCpuTimeReportBtnClick); 596 /** StatsPublisher AppCrashOccurred section */ 597 view.findViewById(R.id.send_on_app_crash_occurred_config) 598 .setOnClickListener(this::onSendAppCrashOccurredConfigBtnClick); 599 view.findViewById(R.id.remove_on_app_crash_occurred_config) 600 .setOnClickListener(this::onRemoveAppCrashOccurredConfigBtnClick); 601 view.findViewById(R.id.get_on_app_crash_occurred_report) 602 .setOnClickListener(this::onGetAppCrashOccurredReportBtnClick); 603 /** StatsPublisher ANROccurred section */ 604 view.findViewById(R.id.send_on_anr_occurred_config) 605 .setOnClickListener(this::onSendAnrOccurredConfigBtnClick); 606 view.findViewById(R.id.remove_on_anr_occurred_config) 607 .setOnClickListener(this::onRemoveAnrOccurredConfigBtnClick); 608 view.findViewById(R.id.get_on_anr_occurred_report) 609 .setOnClickListener(this::onGetAnrOccurredReportBtnClick); 610 /** StatsPublisher WTFOccurred section */ 611 view.findViewById(R.id.send_on_wtf_occurred_config) 612 .setOnClickListener(this::onSendWtfOccurredConfigBtnClick); 613 view.findViewById(R.id.remove_on_wtf_occurred_config) 614 .setOnClickListener(this::onRemoveWtfOccurredConfigBtnClick); 615 view.findViewById(R.id.get_on_wtf_occurred_report) 616 .setOnClickListener(this::onGetWtfOccurredReportBtnClick); 617 /** ConnectivityPublisher wifi_netstats top consumers section */ 618 view.findViewById(R.id.send_on_wifi_netstats_config) 619 .setOnClickListener(this::onSendWifiNetstatsConfigBtnClick); 620 view.findViewById(R.id.remove_on_wifi_netstats_config) 621 .setOnClickListener(this::onRemoveWifiNetstatsConfigBtnClick); 622 view.findViewById(R.id.get_on_wifi_netstats_report) 623 .setOnClickListener(this::onGetWifiNetstatsReportBtnClick); 624 /** StatsPublisher + ConnectivityPublisher section */ 625 view.findViewById(R.id.send_stats_and_connectivity_config) 626 .setOnClickListener(this::onSendStatsAndConnectivityConfigBtnClick); 627 view.findViewById(R.id.remove_stats_and_connectivity_config) 628 .setOnClickListener(this::onRemoveStatsAndConnectivityConfigBtnClick); 629 view.findViewById(R.id.get_stats_and_connectivity_report) 630 .setOnClickListener(this::onGetStatsAndConnectivityReportBtnClick); 631 /** Driving sessions section */ 632 view.findViewById(R.id.send_driving_sessions_config) 633 .setOnClickListener(this::onSendDrivingSessionsConfigBtnClick); 634 view.findViewById(R.id.download_data) 635 .setOnClickListener(this::onDownloadDataBtnClick); 636 view.findViewById(R.id.emulate_suspend_to_RAM) 637 .setOnClickListener(this::onEmulateSuspendToRAMBtnClick); 638 view.findViewById(R.id.emulate_reboot) 639 .setOnClickListener(this::onEmulateRebootBtnClick); 640 view.findViewById(R.id.remove_driving_sessions_config) 641 .setOnClickListener(this::onRemoveDrivingSessionsConfigBtnClick); 642 view.findViewById(R.id.get_driving_sessions_report) 643 .setOnClickListener(this::onGetDrivingSessionsReportBtnClick); 644 /** MemoryPublisher section */ 645 view.findViewById(R.id.send_memory_config) 646 .setOnClickListener(this::onSendMemoryConfigBtnClick); 647 view.findViewById(R.id.remove_memory_config) 648 .setOnClickListener(this::onRemoveMemoryConfigBtnClick); 649 view.findViewById(R.id.get_memory_report) 650 .setOnClickListener(this::onGetMemoryReportBtnClick); 651 /** StatsPublisher process_memory_snapshot */ 652 view.findViewById(R.id.send_on_process_memory_snapshot_config) 653 .setOnClickListener(this::onSendProcessMemorySnapshotConfigBtnClick); 654 view.findViewById(R.id.remove_on_process_memory_snapshot_config) 655 .setOnClickListener(this::onRemoveProcessMemorySnapshotConfigBtnClick); 656 view.findViewById(R.id.get_on_process_memory_snapshot_report) 657 .setOnClickListener(this::onGetProcessMemorySnapshotReportBtnClick); 658 /** StatsPublisher process_start_time */ 659 view.findViewById(R.id.send_on_process_start_time_config) 660 .setOnClickListener(this::onSendProcessStartTimeConfigBtnClick); 661 view.findViewById(R.id.remove_on_process_start_time_config) 662 .setOnClickListener(this::onRemoveProcessStartTimeConfigBtnClick); 663 view.findViewById(R.id.get_on_process_start_time_report) 664 .setOnClickListener(this::onGetProcessStartTimeReportBtnClick); 665 /** Print mem info button */ 666 view.findViewById(R.id.print_mem_info_btn).setOnClickListener(this::onPrintMemInfoBtnClick); 667 return view; 668 } 669 showOutput(String s)670 private void showOutput(String s) { 671 String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS")); 672 String text = now + " : " + s; 673 Log.i(TAG, text); 674 mActivity.runOnUiThread( 675 () -> { 676 mOutputTextView.setText(text + "\n" + mOutputTextView.getText()); 677 }); 678 } 679 toggleMetricsConfigButtons(View view)680 private void toggleMetricsConfigButtons(View view) { 681 boolean visible = mConfigButtonsView.getVisibility() == View.VISIBLE; 682 mConfigButtonsView.setVisibility(visible ? View.GONE : View.VISIBLE); 683 mTootleConfigsBtn.setText(visible ? "Configs ▶" : "Configs ▼"); 684 } 685 enableReportNotification(View view)686 private void enableReportNotification(View view) { 687 mReceiveReportNotification = !mReceiveReportNotification; 688 mEnableReportNotificationButton.setText( 689 getString(R.string.receive_report_notification_text, mReceiveReportNotification)); 690 if (mReceiveReportNotification) { 691 mCarTelemetryManager.setReportReadyListener(mExecutor, this::onReportReady); 692 } else { 693 mCarTelemetryManager.clearReportReadyListener(); 694 } 695 } 696 697 /** Implementation of functional interface {@link CarTelemetryManager.ReportReadyListener}. */ onReportReady(@onNull String metricsConfigName)698 private void onReportReady(@NonNull String metricsConfigName) { 699 String s = "Report for MetricsConfig " + metricsConfigName + " is ready."; 700 showOutput(s); 701 } 702 onSendGearChangeConfigBtnClick(View view)703 private void onSendGearChangeConfigBtnClick(View view) { 704 mCarTelemetryManager.addMetricsConfig( 705 ON_GEAR_CHANGE_CONFIG_NAME, 706 METRICS_CONFIG_ON_GEAR_CHANGE_V1.toByteArray(), 707 mExecutor, 708 mAddMetricsConfigCallback); 709 } 710 onRemoveGearChangeConfigBtnClick(View view)711 private void onRemoveGearChangeConfigBtnClick(View view) { 712 showOutput("Removing MetricsConfig that listens for gear change..."); 713 mCarTelemetryManager.removeMetricsConfig(ON_GEAR_CHANGE_CONFIG_NAME); 714 } 715 onGetGearChangeReportBtnClick(View view)716 private void onGetGearChangeReportBtnClick(View view) { 717 mCarTelemetryManager.getFinishedReport(ON_GEAR_CHANGE_CONFIG_NAME, mExecutor, mListener); 718 } 719 onSendProcessMemoryConfigBtnClick(View view)720 private void onSendProcessMemoryConfigBtnClick(View view) { 721 mCarTelemetryManager.addMetricsConfig( 722 PROCESS_MEMORY_CONFIG_NAME, 723 METRICS_CONFIG_PROCESS_MEMORY_V1.toByteArray(), 724 mExecutor, 725 mAddMetricsConfigCallback); 726 } 727 onRemoveProcessMemoryConfigBtnClick(View view)728 private void onRemoveProcessMemoryConfigBtnClick(View view) { 729 showOutput("Removing MetricsConfig that listens for PROCESS_MEMORY_STATE..."); 730 mCarTelemetryManager.removeMetricsConfig(PROCESS_MEMORY_CONFIG_NAME); 731 } 732 onGetProcessMemoryReportBtnClick(View view)733 private void onGetProcessMemoryReportBtnClick(View view) { 734 mCarTelemetryManager.getFinishedReport(PROCESS_MEMORY_CONFIG_NAME, mExecutor, mListener); 735 } 736 onSendAppStartMemoryStateCapturedConfigBtnClick(View view)737 private void onSendAppStartMemoryStateCapturedConfigBtnClick(View view) { 738 mCarTelemetryManager.addMetricsConfig( 739 APP_START_MEMORY_STATE_CAPTURED_CONFIG_NAME, 740 METRICS_CONFIG_APP_START_MEMORY_V1.toByteArray(), 741 mExecutor, 742 mAddMetricsConfigCallback); 743 } 744 onRemoveAppStartMemoryStateCapturedConfigBtnClick(View view)745 private void onRemoveAppStartMemoryStateCapturedConfigBtnClick(View view) { 746 showOutput("Removing MetricsConfig that listens for APP_START_MEMORY_STATE_CAPTURED..."); 747 mCarTelemetryManager.removeMetricsConfig(APP_START_MEMORY_STATE_CAPTURED_CONFIG_NAME); 748 } 749 onGetAppStartMemoryStateCapturedReportBtnClick(View view)750 private void onGetAppStartMemoryStateCapturedReportBtnClick(View view) { 751 mCarTelemetryManager.getFinishedReport( 752 APP_START_MEMORY_STATE_CAPTURED_CONFIG_NAME, mExecutor, mListener); 753 } 754 onSendActivityForegroundStateChangedConfigBtnClick(View view)755 private void onSendActivityForegroundStateChangedConfigBtnClick(View view) { 756 mCarTelemetryManager.addMetricsConfig( 757 ACTIVITY_FOREGROUND_STATE_CHANGED_CONFIG_NAME, 758 METRICS_CONFIG_ACTIVITY_FOREGROUND_STATE_V1.toByteArray(), 759 mExecutor, 760 mAddMetricsConfigCallback); 761 } 762 onRemoveActivityForegroundStateChangedConfigBtnClick(View view)763 private void onRemoveActivityForegroundStateChangedConfigBtnClick(View view) { 764 showOutput("Removing MetricsConfig that listens for ACTIVITY_FOREGROUND_STATE_CHANGED..."); 765 mCarTelemetryManager.removeMetricsConfig(ACTIVITY_FOREGROUND_STATE_CHANGED_CONFIG_NAME); 766 } 767 onGetActivityForegroundStateChangedReportBtnClick(View view)768 private void onGetActivityForegroundStateChangedReportBtnClick(View view) { 769 mCarTelemetryManager.getFinishedReport( 770 ACTIVITY_FOREGROUND_STATE_CHANGED_CONFIG_NAME, mExecutor, mListener); 771 } 772 onSendProcessCpuTimeConfigBtnClick(View view)773 private void onSendProcessCpuTimeConfigBtnClick(View view) { 774 mCarTelemetryManager.addMetricsConfig( 775 PROCESS_CPU_TIME_CONFIG_NAME, 776 METRICS_CONFIG_PROCESS_CPU_TIME_V1.toByteArray(), 777 mExecutor, 778 mAddMetricsConfigCallback); 779 } 780 onRemoveProcessCpuTimeConfigBtnClick(View view)781 private void onRemoveProcessCpuTimeConfigBtnClick(View view) { 782 showOutput("Removing MetricsConfig that listens for PROCESS_CPU_TIME..."); 783 mCarTelemetryManager.removeMetricsConfig(PROCESS_CPU_TIME_CONFIG_NAME); 784 } 785 onGetProcessCpuTimeReportBtnClick(View view)786 private void onGetProcessCpuTimeReportBtnClick(View view) { 787 mCarTelemetryManager.getFinishedReport(PROCESS_CPU_TIME_CONFIG_NAME, mExecutor, mListener); 788 } 789 onSendAppCrashOccurredConfigBtnClick(View view)790 private void onSendAppCrashOccurredConfigBtnClick(View view) { 791 mCarTelemetryManager.addMetricsConfig( 792 APP_CRASH_OCCURRED_CONFIG_NAME, 793 METRICS_CONFIG_APP_CRASH_OCCURRED_V1.toByteArray(), 794 mExecutor, 795 mAddMetricsConfigCallback); 796 } 797 onRemoveAppCrashOccurredConfigBtnClick(View view)798 private void onRemoveAppCrashOccurredConfigBtnClick(View view) { 799 showOutput("Removing MetricsConfig that listens for APP_CRASH_OCCURRED..."); 800 mCarTelemetryManager.removeMetricsConfig(APP_CRASH_OCCURRED_CONFIG_NAME); 801 } 802 onGetAppCrashOccurredReportBtnClick(View view)803 private void onGetAppCrashOccurredReportBtnClick(View view) { 804 mCarTelemetryManager.getFinishedReport( 805 APP_CRASH_OCCURRED_CONFIG_NAME, mExecutor, mListener); 806 } 807 onSendAnrOccurredConfigBtnClick(View view)808 private void onSendAnrOccurredConfigBtnClick(View view) { 809 mCarTelemetryManager.addMetricsConfig( 810 ANR_OCCURRED_CONFIG_NAME, 811 METRICS_CONFIG_ANR_OCCURRED_V1.toByteArray(), 812 mExecutor, 813 mAddMetricsConfigCallback); 814 } 815 onRemoveAnrOccurredConfigBtnClick(View view)816 private void onRemoveAnrOccurredConfigBtnClick(View view) { 817 showOutput("Removing MetricsConfig that listens for ANR_OCCURRED..."); 818 mCarTelemetryManager.removeMetricsConfig(ANR_OCCURRED_CONFIG_NAME); 819 } 820 onGetAnrOccurredReportBtnClick(View view)821 private void onGetAnrOccurredReportBtnClick(View view) { 822 mCarTelemetryManager.getFinishedReport(ANR_OCCURRED_CONFIG_NAME, mExecutor, mListener); 823 } 824 onSendWtfOccurredConfigBtnClick(View view)825 private void onSendWtfOccurredConfigBtnClick(View view) { 826 mCarTelemetryManager.addMetricsConfig( 827 WTF_OCCURRED_CONFIG_NAME, 828 METRICS_CONFIG_WTF_OCCURRED_V1.toByteArray(), 829 mExecutor, 830 mAddMetricsConfigCallback); 831 } 832 onRemoveWtfOccurredConfigBtnClick(View view)833 private void onRemoveWtfOccurredConfigBtnClick(View view) { 834 showOutput("Removing MetricsConfig that listens for WTF_OCCURRED..."); 835 mCarTelemetryManager.removeMetricsConfig(WTF_OCCURRED_CONFIG_NAME); 836 } 837 onGetWtfOccurredReportBtnClick(View view)838 private void onGetWtfOccurredReportBtnClick(View view) { 839 mCarTelemetryManager.getFinishedReport(WTF_OCCURRED_CONFIG_NAME, mExecutor, mListener); 840 } 841 onSendWifiNetstatsConfigBtnClick(View view)842 private void onSendWifiNetstatsConfigBtnClick(View view) { 843 showOutput("If the config is added successfully, it will produce a report on the top " 844 + "3 wifi network traffic consumers after 1 driving sessions."); 845 mCarTelemetryManager.addMetricsConfig( 846 WIFI_TOP_CONSUMERS_CONFIG_NAME, 847 METRICS_CONFIG_WIFI_TOP_CONSUMERS 848 .toBuilder() 849 .setScript( 850 readTelemetryScript(R.raw.telemetry_stats_and_connectivity_script)) 851 .build() 852 .toByteArray(), 853 mExecutor, 854 mAddMetricsConfigCallback); 855 } 856 onRemoveWifiNetstatsConfigBtnClick(View view)857 private void onRemoveWifiNetstatsConfigBtnClick(View view) { 858 showOutput("Removing MetricsConfig on wifi netstats top consumers..."); 859 mCarTelemetryManager.removeMetricsConfig(WIFI_TOP_CONSUMERS_CONFIG_NAME); 860 } 861 onGetWifiNetstatsReportBtnClick(View view)862 private void onGetWifiNetstatsReportBtnClick(View view) { 863 mCarTelemetryManager.getFinishedReport( 864 WIFI_TOP_CONSUMERS_CONFIG_NAME, mExecutor, mListener); 865 } 866 onSendStatsAndConnectivityConfigBtnClick(View view)867 private void onSendStatsAndConnectivityConfigBtnClick(View view) { 868 String luaScript = readTelemetryScript(R.raw.telemetry_stats_and_connectivity_script); 869 showOutput( 870 "If the config added successfully, emulate power state change by first running:\n" 871 + "$ adb shell cmd car_service suspend\n" 872 + "and, after 1 minute pause:\n" 873 + "$ adb shell cmd car_service resume\n" 874 + "Repeat this 3 times and then pull the report after 10 minutes."); 875 TelemetryProto.MetricsConfig config = 876 METRICS_CONFIG_STATS_AND_CONNECTIVITY_V1.toBuilder().setScript(luaScript).build(); 877 mCarTelemetryManager.addMetricsConfig( 878 STATS_AND_CONNECTIVITY_CONFIG_NAME, 879 config.toByteArray(), 880 mExecutor, 881 mAddMetricsConfigCallback); 882 } 883 readTelemetryScript(@awRes int fileResourceId)884 private String readTelemetryScript(@RawRes int fileResourceId) { 885 try (InputStream is = 886 getResources().openRawResource(fileResourceId)) { 887 byte[] bytes = new byte[is.available()]; 888 is.read(bytes); 889 return new String(bytes); 890 } catch (IOException e) { 891 throw new RuntimeException( 892 "Unable to send MetricsConfig, because reading Lua script from file failed.", 893 e); 894 } 895 } 896 onRemoveStatsAndConnectivityConfigBtnClick(View view)897 private void onRemoveStatsAndConnectivityConfigBtnClick(View view) { 898 showOutput("Removing MetricsConfig that listens for stats data & connectivity data..."); 899 mCarTelemetryManager.removeMetricsConfig(STATS_AND_CONNECTIVITY_CONFIG_NAME); 900 } 901 onGetStatsAndConnectivityReportBtnClick(View view)902 private void onGetStatsAndConnectivityReportBtnClick(View view) { 903 mCarTelemetryManager.getFinishedReport( 904 STATS_AND_CONNECTIVITY_CONFIG_NAME, mExecutor, mListener); 905 } 906 onSendDrivingSessionsConfigBtnClick(View view)907 private void onSendDrivingSessionsConfigBtnClick(View view) { 908 String luaScript = readTelemetryScript(R.raw.telemetry_driving_sessions_script); 909 showOutput( 910 "If the config added successfully, please induce three driving sessions\n" 911 + "by using both Suspend-to-RAM and Reboot buttons and then check " 912 + "generated report\n" 913 + "Suggested sequence: \n" 914 + "1) Load new script\n" 915 + "2) Click DOWNLOAD DATA button and note the size of the file downloaded" 916 + ".\n" 917 + "3) Click on SUSPEND TO RAM to complete the 1st driving session. The " 918 + "app should reappear after a brief break.\n" 919 + "4) Click DOWNLOAD DATA to download the same file the 2nd time.\n" 920 + "5) Click on REBOOT button to complete the 2nd driving session and test" 921 + " preserving of session data on disk at shutdown.\n" 922 + "6) After the reboot is complete, bring up the Kitchensink app and " 923 + "telemetry screen again to continue the test.\n" 924 + "7) Click DOWNLOAD DATA to download the same file the 3rd time.\n" 925 + "8) Click on SUSPEND TO RAM to complete the 3rd driving session.\n" 926 + "9) After the screen and the app are brought back up, click on GET " 927 + "REPORT.\n" 928 + "10) The report requires 3 driving sessions to be generated.\n" 929 + "11) In the report, there will be three separate entries that show " 930 + "total traffic for kitchen sink app.\n" 931 + "12) Each entry corresponds to a driving session.\n" 932 + "13) Each entry should show the number of bytes transferred at least " 933 + "equal to the size of the file downloaded each of the 3 times.\n" 934 ); 935 TelemetryProto.MetricsConfig config = 936 METRICS_CONFIG_DRIVING_SESSIONS.toBuilder().setScript(luaScript).build(); 937 mCarTelemetryManager.addMetricsConfig( 938 WIFI_STATS_DRIVING_SESSIONS_CONFIG_NAME, 939 config.toByteArray(), 940 mExecutor, 941 mAddMetricsConfigCallback); 942 } 943 onDownloadDataBtnClick(View view)944 private void onDownloadDataBtnClick(View view) { 945 showOutput("Downloading data using curl..."); 946 947 // First, create a directory where the file will be downloaded. 948 File tempDirectory; 949 try { 950 tempDirectory = Files.createTempDirectory(mActivity.getFilesDir().toPath(), 951 "downloadDir").toFile(); 952 } catch (IOException e) { 953 showOutput(e.toString()); 954 return; 955 } 956 957 boolean status = runCommand(tempDirectory, "curl", "-O", "-L", 958 "https://yts.devicecertification.youtube/yts_server.zip"); 959 Path filePath = Paths.get(tempDirectory.getAbsolutePath(), "yts_server.zip"); 960 if (status && Files.exists(filePath)) { 961 try { 962 showOutput("Successfully downloaded a file with size " + Files.size(filePath) 963 + " bytes."); 964 } catch (IOException e) { 965 showOutput( 966 "Successfully downloaded a file but exception occurred: " + e.toString()); 967 } 968 } 969 970 // clean up by removing the temporary download directory with all its contents. 971 tempDirectory.delete(); 972 } 973 runCommand(@ullable File currentDirectory, String... command)974 private boolean runCommand(@Nullable File currentDirectory, String... command) { 975 Process p = null; 976 BufferedReader is = null; 977 StringBuilder out = new StringBuilder(); 978 boolean success = false; 979 try { 980 ProcessBuilder processBuilder = new ProcessBuilder(command); 981 processBuilder.redirectErrorStream(true); 982 if (currentDirectory != null) { 983 processBuilder.directory(currentDirectory); 984 } 985 p = processBuilder.start(); 986 is = new BufferedReader(new InputStreamReader(p.getInputStream())); 987 String line; 988 989 while ((line = is.readLine()) != null) { 990 out.append(line); 991 out.append(System.lineSeparator()); 992 } 993 p.waitFor(); 994 } catch (Exception e) { 995 showOutput(e.toString()); 996 } finally { 997 if (p != null) { 998 p.destroy(); 999 } 1000 if (is != null) { 1001 try { 1002 is.close(); 1003 } catch (IOException e) { 1004 // ignore 1005 } 1006 } 1007 } 1008 if (p != null) { 1009 int processExitValue = p.exitValue(); 1010 if (processExitValue == 0) { 1011 showOutput(out.toString().trim()); 1012 success = true; 1013 } 1014 } 1015 return success; 1016 } 1017 onEmulateSuspendToRAMBtnClick(View view)1018 private void onEmulateSuspendToRAMBtnClick(View view) { 1019 runCommand(null, "cmd", "car_service", "suspend", "--simulate", "--wakeup-after", "3"); 1020 } 1021 onEmulateRebootBtnClick(View view)1022 private void onEmulateRebootBtnClick(View view) { 1023 runCommand(null, "cmd", "car_service", "power-off", "--reboot"); 1024 } 1025 onRemoveDrivingSessionsConfigBtnClick(View view)1026 private void onRemoveDrivingSessionsConfigBtnClick(View view) { 1027 showOutput("Removing MetricsConfig that listens for driving sessions..."); 1028 mCarTelemetryManager.removeMetricsConfig(WIFI_STATS_DRIVING_SESSIONS_CONFIG_NAME); 1029 } 1030 onGetDrivingSessionsReportBtnClick(View view)1031 private void onGetDrivingSessionsReportBtnClick(View view) { 1032 mCarTelemetryManager.getFinishedReport( 1033 WIFI_STATS_DRIVING_SESSIONS_CONFIG_NAME, mExecutor, mListener); 1034 } 1035 onSendMemoryConfigBtnClick(View view)1036 private void onSendMemoryConfigBtnClick(View view) { 1037 showOutput("If the MetricsConfig is added successfully, it will produce 3 metrics " 1038 + "reports on available memory. The reports are produced 3 seconds apart. " 1039 + "After 3 reports, the MetricsConfig's lifecycle is considered finished."); 1040 mCarTelemetryManager.addMetricsConfig( 1041 MEMORY_CONFIG_NAME, 1042 METRICS_CONFIG_MEMORY_V1.toByteArray(), 1043 mExecutor, 1044 mAddMetricsConfigCallback); 1045 } 1046 onRemoveMemoryConfigBtnClick(View view)1047 private void onRemoveMemoryConfigBtnClick(View view) { 1048 showOutput("Removing MetricsConfig for memory..."); 1049 mCarTelemetryManager.removeMetricsConfig(MEMORY_CONFIG_NAME); 1050 } 1051 onGetMemoryReportBtnClick(View view)1052 private void onGetMemoryReportBtnClick(View view) { 1053 mCarTelemetryManager.getFinishedReport(MEMORY_CONFIG_NAME, mExecutor, mListener); 1054 } 1055 onSendProcessMemorySnapshotConfigBtnClick(View view)1056 private void onSendProcessMemorySnapshotConfigBtnClick(View view) { 1057 mCarTelemetryManager.addMetricsConfig( 1058 PROCESS_MEMORY_SNAPSHOT_CONFIG_NAME, 1059 METRICS_CONFIG_PROCESS_MEMORY_SNAPSHOT_V1.toByteArray(), 1060 mExecutor, 1061 mAddMetricsConfigCallback); 1062 } 1063 onRemoveProcessMemorySnapshotConfigBtnClick(View view)1064 private void onRemoveProcessMemorySnapshotConfigBtnClick(View view) { 1065 showOutput("Removing MetricsConfig that listens for PROCESS_MEMORY_SNAPSHOT..."); 1066 mCarTelemetryManager.removeMetricsConfig(PROCESS_MEMORY_SNAPSHOT_CONFIG_NAME); 1067 } 1068 onGetProcessMemorySnapshotReportBtnClick(View view)1069 private void onGetProcessMemorySnapshotReportBtnClick(View view) { 1070 mCarTelemetryManager.getFinishedReport( 1071 PROCESS_MEMORY_SNAPSHOT_CONFIG_NAME, mExecutor, mListener); 1072 } 1073 onSendProcessStartTimeConfigBtnClick(View view)1074 private void onSendProcessStartTimeConfigBtnClick(View view) { 1075 mCarTelemetryManager.addMetricsConfig( 1076 PROCESS_START_TIME_CONFIG_NAME, 1077 METRICS_CONFIG_PROCESS_START_TIME_V1.toByteArray(), 1078 mExecutor, 1079 mAddMetricsConfigCallback); 1080 } 1081 onRemoveProcessStartTimeConfigBtnClick(View view)1082 private void onRemoveProcessStartTimeConfigBtnClick(View view) { 1083 showOutput("Removing MetricsConfig that listens for PROCESS_START_TIME..."); 1084 mCarTelemetryManager.removeMetricsConfig(PROCESS_START_TIME_CONFIG_NAME); 1085 } 1086 onGetProcessStartTimeReportBtnClick(View view)1087 private void onGetProcessStartTimeReportBtnClick(View view) { 1088 mCarTelemetryManager.getFinishedReport( 1089 PROCESS_START_TIME_CONFIG_NAME, mExecutor, mListener); 1090 } 1091 1092 /** Gets a MemoryInfo object for the device's current memory status. */ getAvailableMemory()1093 private ActivityManager.MemoryInfo getAvailableMemory() { 1094 ActivityManager activityManager = getActivity().getSystemService(ActivityManager.class); 1095 ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); 1096 activityManager.getMemoryInfo(memoryInfo); 1097 return memoryInfo; 1098 } 1099 onPrintMemInfoBtnClick(View view)1100 private void onPrintMemInfoBtnClick(View view) { 1101 // Use android's "alloc-stress" system tool to create an artificial memory pressure. 1102 ActivityManager.MemoryInfo info = getAvailableMemory(); 1103 showOutput("MemoryInfo availMem=" + (info.availMem / 1024 / 1024) + "/" 1104 + (info.totalMem / 1024 / 1024) + "mb, isLowMem=" + info.lowMemory 1105 + ", threshold=" + (info.threshold / 1024 / 1024) + "mb"); 1106 } 1107 1108 /** 1109 * Updates the view to show {@link CarTelemetryManager#addMetricsConfig(String, byte[], 1110 * Executor, CarTelemetryManager.AddMetricsConfigCallback)} status code. The callbacks are 1111 * executed in {@link #mExecutor}. 1112 */ 1113 private final class AddMetricsConfigCallbackImpl 1114 implements CarTelemetryManager.AddMetricsConfigCallback { 1115 1116 @Override onAddMetricsConfigStatus(@onNull String metricsConfigName, int statusCode)1117 public void onAddMetricsConfigStatus(@NonNull String metricsConfigName, int statusCode) { 1118 showOutput("Add MetricsConfig status for " + metricsConfigName + ": " 1119 + statusCodeToString(statusCode)); 1120 } 1121 statusCodeToString(int statusCode)1122 private String statusCodeToString(int statusCode) { 1123 switch (statusCode) { 1124 case CarTelemetryManager.STATUS_ADD_METRICS_CONFIG_SUCCEEDED: 1125 return "SUCCESS"; 1126 case CarTelemetryManager.STATUS_ADD_METRICS_CONFIG_ALREADY_EXISTS: 1127 return "ERROR ALREADY_EXISTS"; 1128 case CarTelemetryManager.STATUS_ADD_METRICS_CONFIG_VERSION_TOO_OLD: 1129 return "ERROR VERSION_TOO_OLD"; 1130 case CarTelemetryManager.STATUS_ADD_METRICS_CONFIG_PARSE_FAILED: 1131 return "ERROR PARSE_FAILED"; 1132 case CarTelemetryManager.STATUS_ADD_METRICS_CONFIG_SIGNATURE_VERIFICATION_FAILED: 1133 return "ERROR SIGNATURE_VERIFICATION_FAILED"; 1134 default: 1135 return "ERROR UNKNOWN"; 1136 } 1137 } 1138 } 1139 1140 /** 1141 * Implementation of the {@link CarTelemetryManager.MetricsReportCallback}. They update the view 1142 * to show the outputs from the APIs of {@link CarTelemetryManager}. The callbacks are executed 1143 * in {@link mExecutor}. 1144 */ 1145 private final class FinishedReportListenerImpl implements 1146 CarTelemetryManager.MetricsReportCallback { 1147 1148 @Override onResult( @onNull String metricsConfigName, @Nullable PersistableBundle report, @Nullable byte[] telemetryError, @CarTelemetryManager.MetricsReportStatus int status)1149 public void onResult( 1150 @NonNull String metricsConfigName, 1151 @Nullable PersistableBundle report, 1152 @Nullable byte[] telemetryError, 1153 @CarTelemetryManager.MetricsReportStatus int status) { 1154 if (report != null) { 1155 report.size(); // unparcel()'s 1156 showOutput(metricsConfigName + " has status: " 1157 + statusCodeToString(status) + ". Printing report: \n\t" + report); 1158 } else if (telemetryError != null) { 1159 parseError(metricsConfigName, telemetryError); 1160 } else { 1161 showOutput("No report exists for MetricsConfig " + metricsConfigName 1162 + ", reason = " + statusCodeToString(status)); 1163 } 1164 } 1165 parseError(@onNull String metricsConfigName, @NonNull byte[] error)1166 private void parseError(@NonNull String metricsConfigName, @NonNull byte[] error) { 1167 try { 1168 TelemetryProto.TelemetryError telemetryError = 1169 TelemetryProto.TelemetryError.parseFrom(error); 1170 showOutput("Error for " + metricsConfigName + ": " + telemetryError); 1171 } catch (InvalidProtocolBufferException e) { 1172 showOutput("Unable to parse error result for MetricsConfig " + metricsConfigName 1173 + ": " + e.getMessage()); 1174 } 1175 } 1176 statusCodeToString(int statusCode)1177 private String statusCodeToString(int statusCode) { 1178 switch (statusCode) { 1179 case CarTelemetryManager.STATUS_GET_METRICS_CONFIG_FINISHED: 1180 return "REPORT RETRIEVED"; 1181 case CarTelemetryManager.STATUS_GET_METRICS_CONFIG_PENDING: 1182 return "REPORT PENDING"; 1183 case CarTelemetryManager.STATUS_GET_METRICS_CONFIG_INTERIM_RESULTS: 1184 return "INTERIM RESULT EXISTS"; 1185 case CarTelemetryManager.STATUS_GET_METRICS_CONFIG_RUNTIME_ERROR: 1186 return "RUNTIME ERROR"; 1187 case CarTelemetryManager.STATUS_GET_METRICS_CONFIG_DOES_NOT_EXIST: 1188 return "METRICS CONFIG DOES NOT EXIST"; 1189 default: 1190 return "INVALID STATUS CODE"; 1191 } 1192 } 1193 } 1194 } 1195