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 com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.ACTIVITY_FOREGROUND_STATE_CHANGED;
20 import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.ANR_OCCURRED;
21 import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.APP_CRASH_OCCURRED;
22 import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.APP_START_MEMORY_STATE_CAPTURED;
23 import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.PROCESS_CPU_TIME;
24 import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.PROCESS_MEMORY_STATE;
25 import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.WTF_OCCURRED;
26 
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.app.ActivityManager;
30 import android.car.telemetry.CarTelemetryManager;
31 import android.car.telemetry.MetricsConfigKey;
32 import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
33 import android.os.Bundle;
34 import android.os.PersistableBundle;
35 import android.view.LayoutInflater;
36 import android.view.View;
37 import android.view.ViewGroup;
38 import android.widget.TextView;
39 
40 import androidx.fragment.app.Fragment;
41 
42 import com.android.car.telemetry.TelemetryProto;
43 
44 import com.google.android.car.kitchensink.KitchenSinkActivity;
45 import com.google.android.car.kitchensink.R;
46 import com.google.protobuf.InvalidProtocolBufferException;
47 
48 import java.io.ByteArrayInputStream;
49 import java.io.IOException;
50 import java.time.LocalDateTime;
51 import java.time.format.DateTimeFormatter;
52 import java.util.concurrent.Executor;
53 import java.util.concurrent.Executors;
54 
55 public class CarTelemetryTestFragment extends Fragment {
56     private static final int SCRIPT_EXECUTION_PRIORITY_HIGH = 0;
57     private static final int SCRIPT_EXECUTION_PRIORITY_LOW = 100;
58 
59     /** Vehicle property via gear change section. */
60     private static final String LUA_SCRIPT_ON_GEAR_CHANGE =
61             "function onGearChange(published_data, state)\n"
62                     + "    result = {data = \"Hello World!\"}\n"
63                     + "    on_script_finished(result)\n"
64                     + "end\n";
65     private static final TelemetryProto.Publisher VEHICLE_PROPERTY_PUBLISHER =
66             TelemetryProto.Publisher.newBuilder()
67                     .setVehicleProperty(
68                             TelemetryProto.VehiclePropertyPublisher.newBuilder()
69                                     .setVehiclePropertyId(VehicleProperty.GEAR_SELECTION)
70                                     .setReadRate(0f)
71                                     .build()
72                     ).build();
73     private static final TelemetryProto.MetricsConfig METRICS_CONFIG_ON_GEAR_CHANGE_V1 =
74             TelemetryProto.MetricsConfig.newBuilder()
75                     .setName("my_metrics_config")
76                     .setVersion(1)
77                     .setScript(LUA_SCRIPT_ON_GEAR_CHANGE)
78                     .addSubscribers(
79                             TelemetryProto.Subscriber.newBuilder()
80                                     .setHandler("onGearChange")
81                                     .setPublisher(VEHICLE_PROPERTY_PUBLISHER)
82                                     .setPriority(SCRIPT_EXECUTION_PRIORITY_LOW))
83                     .build();
84     private static final MetricsConfigKey ON_GEAR_CHANGE_KEY_V1 = new MetricsConfigKey(
85             METRICS_CONFIG_ON_GEAR_CHANGE_V1.getName(),
86             METRICS_CONFIG_ON_GEAR_CHANGE_V1.getVersion());
87 
88     /** ProcessMemoryState section. */
89     private static final String LUA_SCRIPT_ON_PROCESS_MEMORY_STATE = new StringBuilder()
90             .append("function calculateAverage(tbl)\n")
91             .append("    sum = 0\n")
92             .append("    size = 0\n")
93             .append("    for _, value in ipairs(tbl) do\n")
94             .append("        sum = sum + value\n")
95             .append("        size = size + 1\n")
96             .append("    end\n")
97             .append("    return sum/size\n")
98             .append("end\n")
99             .append("function onProcessMemory(published_data, state)\n")
100             .append("    result = {}\n")
101             .append("    result.page_fault_avg = calculateAverage(published_data.page_fault)\n")
102             .append("    result.major_page_fault_avg = calculateAverage("
103                     + "published_data.page_major_fault)\n")
104             .append("    result.oom_adj_score_avg = calculateAverage("
105                     + "published_data.oom_adj_score)\n")
106             .append("    result.rss_in_bytes_avg = calculateAverage("
107                     + "published_data.rss_in_bytes)\n")
108             .append("    result.swap_in_bytes_avg = calculateAverage("
109                     + "published_data.swap_in_bytes)\n")
110             .append("    result.cache_in_bytes_avg = calculateAverage("
111                     + "published_data.cache_in_bytes)\n")
112             .append("    on_script_finished(result)\n")
113             .append("end\n")
114             .toString();
115     private static final TelemetryProto.Publisher PROCESS_MEMORY_PUBLISHER =
116             TelemetryProto.Publisher.newBuilder()
117                     .setStats(
118                             TelemetryProto.StatsPublisher.newBuilder()
119                                     .setSystemMetric(PROCESS_MEMORY_STATE)
120                     ).build();
121     private static final TelemetryProto.MetricsConfig METRICS_CONFIG_PROCESS_MEMORY_V1 =
122             TelemetryProto.MetricsConfig.newBuilder()
123                     .setName("process_memory_metrics_config")
124                     .setVersion(1)
125                     .setScript(LUA_SCRIPT_ON_PROCESS_MEMORY_STATE)
126                     .addSubscribers(
127                             TelemetryProto.Subscriber.newBuilder()
128                                     .setHandler("onProcessMemory")
129                                     .setPublisher(PROCESS_MEMORY_PUBLISHER)
130                                     .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
131                     .build();
132     private static final MetricsConfigKey PROCESS_MEMORY_KEY_V1 = new MetricsConfigKey(
133             METRICS_CONFIG_PROCESS_MEMORY_V1.getName(),
134             METRICS_CONFIG_PROCESS_MEMORY_V1.getVersion());
135 
136     /** AppStartMemoryStateCaptured section. */
137     private static final String LUA_SCRIPT_ON_APP_START_MEMORY_STATE_CAPTURED = new StringBuilder()
138             .append("function calculateAverage(tbl)\n")
139             .append("    sum = 0\n")
140             .append("    size = 0\n")
141             .append("    for _, value in ipairs(tbl) do\n")
142             .append("        sum = sum + value\n")
143             .append("        size = size + 1\n")
144             .append("    end\n")
145             .append("    return sum/size\n")
146             .append("end\n")
147             .append("function onAppStartMemoryStateCaptured(published_data, state)\n")
148             .append("    result = {}\n")
149             .append("    result.uid = published_data.uid\n")
150             .append("    result.page_fault_avg = calculateAverage(published_data.page_fault)\n")
151             .append("    result.major_page_fault_avg = calculateAverage("
152                     + "published_data.page_major_fault)\n")
153             .append("    result.rss_in_bytes_avg = calculateAverage("
154                     + "published_data.rss_in_bytes)\n")
155             .append("    result.swap_in_bytes_avg = calculateAverage("
156                     + "published_data.swap_in_bytes)\n")
157             .append("    result.cache_in_bytes_avg = calculateAverage("
158                     + "published_data.cache_in_bytes)\n")
159             .append("    on_script_finished(result)\n")
160             .append("end\n")
161             .toString();
162     private static final TelemetryProto.Publisher APP_START_MEMORY_STATE_CAPTURED_PUBLISHER =
163             TelemetryProto.Publisher.newBuilder()
164                     .setStats(
165                             TelemetryProto.StatsPublisher.newBuilder()
166                                     .setSystemMetric(APP_START_MEMORY_STATE_CAPTURED)
167                     ).build();
168     private static final TelemetryProto.MetricsConfig METRICS_CONFIG_APP_START_MEMORY_V1 =
169             TelemetryProto.MetricsConfig.newBuilder()
170                     .setName("app_start_memory_metrics_config")
171                     .setVersion(1)
172                     .setScript(LUA_SCRIPT_ON_APP_START_MEMORY_STATE_CAPTURED)
173                     .addSubscribers(
174                             TelemetryProto.Subscriber.newBuilder()
175                                     .setHandler("onAppStartMemoryStateCaptured")
176                                     .setPublisher(APP_START_MEMORY_STATE_CAPTURED_PUBLISHER)
177                                     .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
178                     .build();
179     private static final MetricsConfigKey APP_START_MEMORY_STATE_CAPTURED_KEY_V1 =
180             new MetricsConfigKey(
181                     METRICS_CONFIG_APP_START_MEMORY_V1.getName(),
182                     METRICS_CONFIG_APP_START_MEMORY_V1.getVersion());
183 
184     /** ActivityForegroundStateChanged section. */
185     private static final String LUA_SCRIPT_ON_ACTIVITY_FOREGROUND_STATE_CHANGED =
186             new StringBuilder()
187                     .append("function onActivityForegroundStateChanged(published_data, state)\n")
188                     .append("    result = {}\n")
189                     .append("    n = 0\n")
190                     .append("    for k, v in pairs(published_data) do\n")
191                     .append("        result[k] = v[1]\n")
192                     .append("        n = n + 1\n")
193                     .append("    end\n")
194                     .append("    result.n = n\n")
195                     .append("    on_script_finished(result)\n")
196                     .append("end\n")
197                     .toString();
198     private static final TelemetryProto.Publisher ACTIVITY_FOREGROUND_STATE_CHANGED_PUBLISHER =
199             TelemetryProto.Publisher.newBuilder()
200                     .setStats(
201                             TelemetryProto.StatsPublisher.newBuilder()
202                                     .setSystemMetric(ACTIVITY_FOREGROUND_STATE_CHANGED)
203                     ).build();
204     private static final TelemetryProto.MetricsConfig METRICS_CONFIG_ACTIVITY_FOREGROUND_STATE_V1 =
205             TelemetryProto.MetricsConfig.newBuilder()
206                     .setName("activity_foreground_state_changed_config")
207                     .setVersion(1)
208                     .setScript(LUA_SCRIPT_ON_ACTIVITY_FOREGROUND_STATE_CHANGED)
209                     .addSubscribers(
210                             TelemetryProto.Subscriber.newBuilder()
211                                     .setHandler("onActivityForegroundStateChanged")
212                                     .setPublisher(ACTIVITY_FOREGROUND_STATE_CHANGED_PUBLISHER)
213                                     .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
214                     .build();
215     private static final MetricsConfigKey ACTIVITY_FOREGROUND_STATE_CHANGED_KEY_V1 =
216             new MetricsConfigKey(
217                     METRICS_CONFIG_ACTIVITY_FOREGROUND_STATE_V1.getName(),
218                     METRICS_CONFIG_ACTIVITY_FOREGROUND_STATE_V1.getVersion());
219 
220     /** ProcessCpuTime section */
221     private static final String LUA_SCRIPT_ON_PROCESS_CPU_TIME =
222             new StringBuilder()
223                     .append("function onProcessCpuTime(published_data, state)\n")
224                     .append("    result = {}\n")
225                     .append("    n = 0\n")
226                     .append("    for k, v in pairs(published_data) do\n")
227                     .append("        result[k] = v[1]\n")
228                     .append("        n = n + 1\n")
229                     .append("    end\n")
230                     .append("    result.n = n\n")
231                     .append("    on_script_finished(result)\n")
232                     .append("end\n")
233                     .toString();
234     private static final TelemetryProto.Publisher PROCESS_CPU_TIME_PUBLISHER =
235             TelemetryProto.Publisher.newBuilder()
236                     .setStats(
237                             TelemetryProto.StatsPublisher.newBuilder()
238                                     .setSystemMetric(PROCESS_CPU_TIME)
239                     ).build();
240     private static final TelemetryProto.MetricsConfig METRICS_CONFIG_PROCESS_CPU_TIME_V1 =
241             TelemetryProto.MetricsConfig.newBuilder()
242                     .setName("process_cpu_time_config")
243                     .setVersion(1)
244                     .setScript(LUA_SCRIPT_ON_PROCESS_CPU_TIME)
245                     .addSubscribers(
246                             TelemetryProto.Subscriber.newBuilder()
247                                     .setHandler("onProcessCpuTime")
248                                     .setPublisher(PROCESS_CPU_TIME_PUBLISHER)
249                                     .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
250                     .build();
251     private static final MetricsConfigKey PROCESS_CPU_TIME_KEY_V1 =
252             new MetricsConfigKey(
253                     METRICS_CONFIG_PROCESS_CPU_TIME_V1.getName(),
254                     METRICS_CONFIG_PROCESS_CPU_TIME_V1.getVersion());
255 
256     /** AppCrashOccurred section */
257     private static final String LUA_SCRIPT_ON_APP_CRASH_OCCURRED =
258             new StringBuilder()
259                     .append("function onAppCrashOccurred(published_data, state)\n")
260                     .append("    on_script_finished(published_data)\n")
261                     .append("end\n")
262                     .toString();
263     private static final TelemetryProto.Publisher APP_CRASH_OCCURRED_PUBLISHER =
264             TelemetryProto.Publisher.newBuilder()
265                     .setStats(
266                             TelemetryProto.StatsPublisher.newBuilder()
267                                     .setSystemMetric(APP_CRASH_OCCURRED)
268                     ).build();
269     private static final TelemetryProto.MetricsConfig METRICS_CONFIG_APP_CRASH_OCCURRED_V1 =
270             TelemetryProto.MetricsConfig.newBuilder()
271                     .setName("app_crash_occurred_config")
272                     .setVersion(1)
273                     .setScript(LUA_SCRIPT_ON_APP_CRASH_OCCURRED)
274                     .addSubscribers(
275                             TelemetryProto.Subscriber.newBuilder()
276                                     .setHandler("onAppCrashOccurred")
277                                     .setPublisher(APP_CRASH_OCCURRED_PUBLISHER)
278                                     .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
279                     .build();
280     private static final MetricsConfigKey APP_CRASH_OCCURRED_KEY_V1 =
281             new MetricsConfigKey(
282                     METRICS_CONFIG_APP_CRASH_OCCURRED_V1.getName(),
283                     METRICS_CONFIG_APP_CRASH_OCCURRED_V1.getVersion());
284 
285     /** ANROccurred section */
286     private static final String LUA_SCRIPT_ON_ANR_OCCURRED =
287             new StringBuilder()
288                     .append("function onAnrOccurred(published_data, state)\n")
289                     .append("    on_script_finished(published_data)\n")
290                     .append("end\n")
291                     .toString();
292     private static final TelemetryProto.Publisher ANR_OCCURRED_PUBLISHER =
293             TelemetryProto.Publisher.newBuilder()
294                     .setStats(
295                             TelemetryProto.StatsPublisher.newBuilder()
296                                     .setSystemMetric(ANR_OCCURRED)
297                     ).build();
298     private static final TelemetryProto.MetricsConfig METRICS_CONFIG_ANR_OCCURRED_V1 =
299             TelemetryProto.MetricsConfig.newBuilder()
300                     .setName("anr_occurred_config")
301                     .setVersion(1)
302                     .setScript(LUA_SCRIPT_ON_ANR_OCCURRED)
303                     .addSubscribers(
304                             TelemetryProto.Subscriber.newBuilder()
305                                     .setHandler("onAnrOccurred")
306                                     .setPublisher(ANR_OCCURRED_PUBLISHER)
307                                     .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
308                     .build();
309     private static final MetricsConfigKey ANR_OCCURRED_KEY_V1 =
310             new MetricsConfigKey(
311                     METRICS_CONFIG_ANR_OCCURRED_V1.getName(),
312                     METRICS_CONFIG_ANR_OCCURRED_V1.getVersion());
313 
314     /** WTFOccurred section */
315     private static final String LUA_SCRIPT_ON_WTF_OCCURRED =
316             new StringBuilder()
317                     .append("function onWtfOccurred(published_data, state)\n")
318                     .append("    on_script_finished(published_data)\n")
319                     .append("end\n")
320                     .toString();
321     private static final TelemetryProto.Publisher WTF_OCCURRED_PUBLISHER =
322             TelemetryProto.Publisher.newBuilder()
323                     .setStats(
324                             TelemetryProto.StatsPublisher.newBuilder()
325                                     .setSystemMetric(WTF_OCCURRED)
326                     ).build();
327     private static final TelemetryProto.MetricsConfig METRICS_CONFIG_WTF_OCCURRED_V1 =
328             TelemetryProto.MetricsConfig.newBuilder()
329                     .setName("wtf_occurred_config")
330                     .setVersion(1)
331                     .setScript(LUA_SCRIPT_ON_WTF_OCCURRED)
332                     .addSubscribers(
333                             TelemetryProto.Subscriber.newBuilder()
334                                     .setHandler("onWtfOccurred")
335                                     .setPublisher(WTF_OCCURRED_PUBLISHER)
336                                     .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
337                     .build();
338     private static final MetricsConfigKey WTF_OCCURRED_KEY_V1 =
339             new MetricsConfigKey(
340                     METRICS_CONFIG_WTF_OCCURRED_V1.getName(),
341                     METRICS_CONFIG_WTF_OCCURRED_V1.getVersion());
342 
343     private final Executor mExecutor = Executors.newSingleThreadExecutor();
344 
345     private CarTelemetryManager mCarTelemetryManager;
346     private CarTelemetryResultsListenerImpl mListener;
347     private KitchenSinkActivity mActivity;
348     private TextView mOutputTextView;
349 
350     @Override
onCreate(@ullable Bundle savedInstanceState)351     public void onCreate(@Nullable Bundle savedInstanceState) {
352         mActivity = (KitchenSinkActivity) getActivity();
353         mCarTelemetryManager = mActivity.getCarTelemetryManager();
354         mListener = new CarTelemetryResultsListenerImpl();
355         mCarTelemetryManager.setListener(mExecutor, mListener);
356         super.onCreate(savedInstanceState);
357     }
358 
359     @Nullable
360     @Override
onCreateView( @onNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)361     public View onCreateView(
362             @NonNull LayoutInflater inflater,
363             @Nullable ViewGroup container,
364             @Nullable Bundle savedInstanceState) {
365         View view = inflater.inflate(R.layout.car_telemetry_test, container, false);
366         mOutputTextView = view.findViewById(R.id.output_textview);
367         view.findViewById(R.id.send_on_gear_change_config)
368                 .setOnClickListener(this::onSendGearChangeConfigBtnClick);
369         view.findViewById(R.id.remove_on_gear_change_config)
370                 .setOnClickListener(this::onRemoveGearChangeConfigBtnClick);
371         view.findViewById(R.id.get_on_gear_change_report)
372                 .setOnClickListener(this::onGetGearChangeReportBtnClick);
373         view.findViewById(R.id.send_on_process_memory_config)
374                 .setOnClickListener(this::onSendProcessMemoryConfigBtnClick);
375         view.findViewById(R.id.remove_on_process_memory_config)
376                 .setOnClickListener(this::onRemoveProcessMemoryConfigBtnClick);
377         view.findViewById(R.id.get_on_process_memory_report)
378                 .setOnClickListener(this::onGetProcessMemoryReportBtnClick);
379         view.findViewById(R.id.send_on_app_start_memory_state_captured_config)
380                 .setOnClickListener(this::onSendAppStartMemoryStateCapturedConfigBtnClick);
381         view.findViewById(R.id.remove_on_app_start_memory_state_captured_config)
382                 .setOnClickListener(this::onRemoveAppStartMemoryStateCapturedConfigBtnClick);
383         view.findViewById(R.id.get_on_app_start_memory_state_captured_report)
384                 .setOnClickListener(this::onGetAppStartMemoryStateCapturedReportBtnClick);
385         view.findViewById(R.id.send_on_activity_foreground_state_changed_config)
386                 .setOnClickListener(this::onSendActivityForegroundStateChangedConfigBtnClick);
387         view.findViewById(R.id.remove_on_activity_foreground_state_changed_config)
388                 .setOnClickListener(this::onRemoveActivityForegroundStateChangedConfigBtnClick);
389         view.findViewById(R.id.get_on_activity_foreground_state_changed_report)
390                 .setOnClickListener(this::onGetActivityForegroundStateChangedReportBtnClick);
391         view.findViewById(R.id.send_on_process_cpu_time_config)
392                 .setOnClickListener(this::onSendProcessCpuTimeConfigBtnClick);
393         view.findViewById(R.id.remove_on_process_cpu_time_config)
394                 .setOnClickListener(this::onRemoveProcessCpuTimeConfigBtnClick);
395         view.findViewById(R.id.get_on_process_cpu_time_report)
396                 .setOnClickListener(this::onGetProcessCpuTimeReportBtnClick);
397         /** AppCrashOccurred section */
398         view.findViewById(R.id.send_on_app_crash_occurred_config)
399                 .setOnClickListener(this::onSendAppCrashOccurredConfigBtnClick);
400         view.findViewById(R.id.remove_on_app_crash_occurred_config)
401                 .setOnClickListener(this::onRemoveAppCrashOccurredConfigBtnClick);
402         view.findViewById(R.id.get_on_app_crash_occurred_report)
403                 .setOnClickListener(this::onGetAppCrashOccurredReportBtnClick);
404         /** ANROccurred section */
405         view.findViewById(R.id.send_on_anr_occurred_config)
406                 .setOnClickListener(this::onSendAnrOccurredConfigBtnClick);
407         view.findViewById(R.id.remove_on_anr_occurred_config)
408                 .setOnClickListener(this::onRemoveAnrOccurredConfigBtnClick);
409         view.findViewById(R.id.get_on_anr_occurred_report)
410                 .setOnClickListener(this::onGetAnrOccurredReportBtnClick);
411         /** WTFOccurred section */
412         view.findViewById(R.id.send_on_wtf_occurred_config)
413                 .setOnClickListener(this::onSendWtfOccurredConfigBtnClick);
414         view.findViewById(R.id.remove_on_wtf_occurred_config)
415                 .setOnClickListener(this::onRemoveWtfOccurredConfigBtnClick);
416         view.findViewById(R.id.get_on_wtf_occurred_report)
417                 .setOnClickListener(this::onGetWtfOccurredReportBtnClick);
418         view.findViewById(R.id.show_mem_info_btn).setOnClickListener(this::onShowMemInfoBtnClick);
419         return view;
420     }
421 
showOutput(String s)422     private void showOutput(String s) {
423         mActivity.runOnUiThread(() -> {
424             String now = LocalDateTime.now()
425                     .format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS"));
426             mOutputTextView.setText(
427                     now + " : " + s + "\n" + mOutputTextView.getText());
428         });
429     }
430 
onSendGearChangeConfigBtnClick(View view)431     private void onSendGearChangeConfigBtnClick(View view) {
432         showOutput("Sending MetricsConfig that listen for gear change...");
433         mCarTelemetryManager.addMetricsConfig(ON_GEAR_CHANGE_KEY_V1,
434                 METRICS_CONFIG_ON_GEAR_CHANGE_V1.toByteArray());
435     }
436 
onRemoveGearChangeConfigBtnClick(View view)437     private void onRemoveGearChangeConfigBtnClick(View view) {
438         showOutput("Removing MetricsConfig that listens for gear change...");
439         mCarTelemetryManager.removeMetricsConfig(ON_GEAR_CHANGE_KEY_V1);
440     }
441 
onGetGearChangeReportBtnClick(View view)442     private void onGetGearChangeReportBtnClick(View view) {
443         showOutput("Fetching report for on_gear_change... If nothing shows up within 5 seconds, "
444                 + "there is no result yet");
445         mCarTelemetryManager.sendFinishedReports(ON_GEAR_CHANGE_KEY_V1);
446     }
447 
onSendProcessMemoryConfigBtnClick(View view)448     private void onSendProcessMemoryConfigBtnClick(View view) {
449         showOutput("Sending MetricsConfig that listens for PROCESS_MEMORY_STATE...");
450         mCarTelemetryManager.addMetricsConfig(PROCESS_MEMORY_KEY_V1,
451                 METRICS_CONFIG_PROCESS_MEMORY_V1.toByteArray());
452     }
453 
onRemoveProcessMemoryConfigBtnClick(View view)454     private void onRemoveProcessMemoryConfigBtnClick(View view) {
455         showOutput("Removing MetricsConfig that listens for PROCESS_MEMORY_STATE...");
456         mCarTelemetryManager.removeMetricsConfig(PROCESS_MEMORY_KEY_V1);
457     }
458 
onGetProcessMemoryReportBtnClick(View view)459     private void onGetProcessMemoryReportBtnClick(View view) {
460         showOutput("Fetching report for PROCESS_MEMORY_STATE... If nothing shows up within 5 "
461                 + "seconds, there is no result yet");
462         mCarTelemetryManager.sendFinishedReports(PROCESS_MEMORY_KEY_V1);
463     }
464 
onSendAppStartMemoryStateCapturedConfigBtnClick(View view)465     private void onSendAppStartMemoryStateCapturedConfigBtnClick(View view) {
466         showOutput("Sending MetricsConfig that listens for APP_START_MEMORY_STATE_CAPTURED...");
467         mCarTelemetryManager.addMetricsConfig(APP_START_MEMORY_STATE_CAPTURED_KEY_V1,
468                 METRICS_CONFIG_APP_START_MEMORY_V1.toByteArray());
469     }
470 
onRemoveAppStartMemoryStateCapturedConfigBtnClick(View view)471     private void onRemoveAppStartMemoryStateCapturedConfigBtnClick(View view) {
472         showOutput("Removing MetricsConfig that listens for APP_START_MEMORY_STATE_CAPTURED...");
473         mCarTelemetryManager.removeMetricsConfig(APP_START_MEMORY_STATE_CAPTURED_KEY_V1);
474     }
475 
onGetAppStartMemoryStateCapturedReportBtnClick(View view)476     private void onGetAppStartMemoryStateCapturedReportBtnClick(View view) {
477         showOutput("Fetching report for APP_START_MEMORY_STATE_CAPTURED... "
478                 + "If nothing shows up within 5 seconds, there is no result yet");
479         mCarTelemetryManager.sendFinishedReports(APP_START_MEMORY_STATE_CAPTURED_KEY_V1);
480     }
481 
onSendActivityForegroundStateChangedConfigBtnClick(View view)482     private void onSendActivityForegroundStateChangedConfigBtnClick(View view) {
483         showOutput("Sending MetricsConfig that listens for ACTIVITY_FOREGROUND_STATE_CHANGED...");
484         mCarTelemetryManager.addMetricsConfig(ACTIVITY_FOREGROUND_STATE_CHANGED_KEY_V1,
485                 METRICS_CONFIG_ACTIVITY_FOREGROUND_STATE_V1.toByteArray());
486     }
487 
onRemoveActivityForegroundStateChangedConfigBtnClick(View view)488     private void onRemoveActivityForegroundStateChangedConfigBtnClick(View view) {
489         showOutput("Removing MetricsConfig that listens for ACTIVITY_FOREGROUND_STATE_CHANGED...");
490         mCarTelemetryManager.removeMetricsConfig(ACTIVITY_FOREGROUND_STATE_CHANGED_KEY_V1);
491     }
492 
onGetActivityForegroundStateChangedReportBtnClick(View view)493     private void onGetActivityForegroundStateChangedReportBtnClick(View view) {
494         showOutput("Fetching report for ACTIVITY_FOREGROUND_STATE_CHANGED... "
495                 + "If nothing shows up within 5 seconds, there is no result yet");
496         mCarTelemetryManager.sendFinishedReports(ACTIVITY_FOREGROUND_STATE_CHANGED_KEY_V1);
497     }
498 
onSendProcessCpuTimeConfigBtnClick(View view)499     private void onSendProcessCpuTimeConfigBtnClick(View view) {
500         showOutput("Sending MetricsConfig that listens for PROCESS_CPU_TIME...");
501         mCarTelemetryManager.addMetricsConfig(PROCESS_CPU_TIME_KEY_V1,
502                 METRICS_CONFIG_PROCESS_CPU_TIME_V1.toByteArray());
503     }
504 
onRemoveProcessCpuTimeConfigBtnClick(View view)505     private void onRemoveProcessCpuTimeConfigBtnClick(View view) {
506         showOutput("Removing MetricsConfig that listens for PROCESS_CPU_TIME...");
507         mCarTelemetryManager.removeMetricsConfig(PROCESS_CPU_TIME_KEY_V1);
508     }
509 
onGetProcessCpuTimeReportBtnClick(View view)510     private void onGetProcessCpuTimeReportBtnClick(View view) {
511         showOutput("Fetching report for PROCESS_CPU_TIME... If nothing shows up within 5 "
512                 + "seconds, there is no result yet");
513         mCarTelemetryManager.sendFinishedReports(PROCESS_CPU_TIME_KEY_V1);
514     }
515 
onSendAppCrashOccurredConfigBtnClick(View view)516     private void onSendAppCrashOccurredConfigBtnClick(View view) {
517         showOutput("Sending MetricsConfig that listens for APP_CRASH_OCCURRED...");
518         mCarTelemetryManager.addMetricsConfig(APP_CRASH_OCCURRED_KEY_V1,
519                 METRICS_CONFIG_APP_CRASH_OCCURRED_V1.toByteArray());
520     }
521 
onRemoveAppCrashOccurredConfigBtnClick(View view)522     private void onRemoveAppCrashOccurredConfigBtnClick(View view) {
523         showOutput("Removing MetricsConfig that listens for APP_CRASH_OCCURRED...");
524         mCarTelemetryManager.removeMetricsConfig(APP_CRASH_OCCURRED_KEY_V1);
525     }
526 
onGetAppCrashOccurredReportBtnClick(View view)527     private void onGetAppCrashOccurredReportBtnClick(View view) {
528         showOutput("Fetching report for APP_CRASH_OCCURRED... If nothing shows up within 5 "
529                 + "seconds, there is no result yet");
530         mCarTelemetryManager.sendFinishedReports(APP_CRASH_OCCURRED_KEY_V1);
531     }
532 
onSendAnrOccurredConfigBtnClick(View view)533     private void onSendAnrOccurredConfigBtnClick(View view) {
534         showOutput("Sending MetricsConfig that listens for ANR_OCCURRED...");
535         mCarTelemetryManager.addMetricsConfig(ANR_OCCURRED_KEY_V1,
536                 METRICS_CONFIG_ANR_OCCURRED_V1.toByteArray());
537     }
538 
onRemoveAnrOccurredConfigBtnClick(View view)539     private void onRemoveAnrOccurredConfigBtnClick(View view) {
540         showOutput("Removing MetricsConfig that listens for ANR_OCCURRED...");
541         mCarTelemetryManager.removeMetricsConfig(ANR_OCCURRED_KEY_V1);
542     }
543 
onGetAnrOccurredReportBtnClick(View view)544     private void onGetAnrOccurredReportBtnClick(View view) {
545         showOutput("Fetching report for ANR_OCCURRED... If nothing shows up within 5 "
546                 + "seconds, there is no result yet");
547         mCarTelemetryManager.sendFinishedReports(ANR_OCCURRED_KEY_V1);
548     }
549 
onSendWtfOccurredConfigBtnClick(View view)550     private void onSendWtfOccurredConfigBtnClick(View view) {
551         showOutput("Sending MetricsConfig that listens for WTF_OCCURRED...");
552         mCarTelemetryManager.addMetricsConfig(WTF_OCCURRED_KEY_V1,
553                 METRICS_CONFIG_WTF_OCCURRED_V1.toByteArray());
554     }
555 
onRemoveWtfOccurredConfigBtnClick(View view)556     private void onRemoveWtfOccurredConfigBtnClick(View view) {
557         showOutput("Removing MetricsConfig that listens for WTF_OCCURRED...");
558         mCarTelemetryManager.removeMetricsConfig(WTF_OCCURRED_KEY_V1);
559     }
560 
onGetWtfOccurredReportBtnClick(View view)561     private void onGetWtfOccurredReportBtnClick(View view) {
562         showOutput("Fetching report for WTF_OCCURRED... If nothing shows up within 5 "
563                 + "seconds, there is no result yet");
564         mCarTelemetryManager.sendFinishedReports(WTF_OCCURRED_KEY_V1);
565     }
566 
567     /** Gets a MemoryInfo object for the device's current memory status. */
getAvailableMemory()568     private ActivityManager.MemoryInfo getAvailableMemory() {
569         ActivityManager activityManager = getActivity().getSystemService(ActivityManager.class);
570         ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
571         activityManager.getMemoryInfo(memoryInfo);
572         return memoryInfo;
573     }
574 
onShowMemInfoBtnClick(View view)575     private void onShowMemInfoBtnClick(View view) {
576         // Use android's "alloc-stress" system tool to create an artificial memory pressure.
577         ActivityManager.MemoryInfo info = getAvailableMemory();
578         showOutput("MemoryInfo availMem=" + (info.availMem / 1024 / 1024) + "/"
579                 + (info.totalMem / 1024 / 1024) + "mb, isLowMem=" + info.lowMemory
580                 + ", threshold=" + (info.threshold / 1024 / 1024) + "mb");
581     }
582 
583     @Override
onDestroyView()584     public void onDestroyView() {
585         super.onDestroyView();
586     }
587 
588     /**
589      * Implementation of the {@link CarTelemetryManager.CarTelemetryResultsListener}. They update
590      * the view to show the outputs from the APIs of {@link CarTelemetryManager}.
591      * The callbacks are executed in {@link mExecutor}.
592      */
593     private final class CarTelemetryResultsListenerImpl
594             implements CarTelemetryManager.CarTelemetryResultsListener {
595 
596         @Override
onResult(@onNull MetricsConfigKey key, @NonNull byte[] result)597         public void onResult(@NonNull MetricsConfigKey key, @NonNull byte[] result) {
598             PersistableBundle bundle;
599             try (ByteArrayInputStream bis = new ByteArrayInputStream(result)) {
600                 bundle = PersistableBundle.readFromStream(bis);
601             } catch (IOException e) {
602                 bundle = null;
603             }
604             showOutput("Result for " + key.getName() + ": " + bundle.toString());
605         }
606 
607         @Override
onError(@onNull MetricsConfigKey key, @NonNull byte[] error)608         public void onError(@NonNull MetricsConfigKey key, @NonNull byte[] error) {
609             try {
610                 TelemetryProto.TelemetryError telemetryError =
611                         TelemetryProto.TelemetryError.parseFrom(error);
612                 showOutput("Error for " + key.getName() + ": " + telemetryError);
613             } catch (InvalidProtocolBufferException e) {
614                 showOutput("Unable to parse error result for MetricsConfig " + key.getName()
615                         + ": " + e.getMessage());
616             }
617         }
618 
619         @Override
onAddMetricsConfigStatus(@onNull MetricsConfigKey key, int statusCode)620         public void onAddMetricsConfigStatus(@NonNull MetricsConfigKey key, int statusCode) {
621             showOutput("Add MetricsConfig status for " + key.getName() + ": "
622                     + statusCodeToString(statusCode));
623         }
624 
statusCodeToString(int statusCode)625         private String statusCodeToString(int statusCode) {
626             switch (statusCode) {
627                 case CarTelemetryManager.ERROR_METRICS_CONFIG_NONE:
628                     return "SUCCESS";
629                 case CarTelemetryManager.ERROR_METRICS_CONFIG_ALREADY_EXISTS:
630                     return "ERROR ALREADY_EXISTS";
631                 case CarTelemetryManager.ERROR_METRICS_CONFIG_VERSION_TOO_OLD:
632                     return "ERROR VERSION_TOO_OLD";
633                 case CarTelemetryManager.ERROR_METRICS_CONFIG_PARSE_FAILED:
634                     return "ERROR PARSE_FAILED";
635                 case CarTelemetryManager.ERROR_METRICS_CONFIG_SIGNATURE_VERIFICATION_FAILED:
636                     return "ERROR SIGNATURE_VERIFICATION_FAILED";
637                 default:
638                     return "ERROR UNKNOWN";
639             }
640         }
641     }
642 }
643