1 /* 2 * Copyright (C) 2022 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.android.car.telemetry.util; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.car.builtin.util.Slogf; 22 import android.os.PersistableBundle; 23 24 import com.android.car.CarLog; 25 import com.android.car.telemetry.MetricsReportProto.MetricsReportContainer; 26 import com.android.car.telemetry.MetricsReportProto.MetricsReportList; 27 28 import com.google.protobuf.ByteString; 29 30 import java.io.ByteArrayInputStream; 31 import java.io.ByteArrayOutputStream; 32 import java.io.IOException; 33 34 /** Utility class for working with {@link com.android.car.telemetry.MetricsReportProto}. */ 35 public final class MetricsReportProtoUtils { 36 MetricsReportProtoUtils()37 private MetricsReportProtoUtils() { } 38 39 /** 40 * Serialize a PersistableBundle into bytes. If conversion failed, return null. 41 */ 42 @Nullable getBytes(PersistableBundle bundle)43 public static byte[] getBytes(PersistableBundle bundle) { 44 try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { 45 bundle.writeToStream(byteArrayOutputStream); 46 return byteArrayOutputStream.toByteArray(); 47 } catch (IOException e) { 48 Slogf.w(CarLog.TAG_TELEMETRY, "Serializing PersistableBundle failed.", e); 49 } 50 return null; 51 } 52 53 /** 54 * Serialize a PersistableBundle into ByteString, which is an immutable byte array. 55 * ByteString is the corresponding Java type for {@code bytes} in protobuf. 56 */ 57 @Nullable getByteString(PersistableBundle bundle)58 public static ByteString getByteString(PersistableBundle bundle) { 59 byte[] bytes = getBytes(bundle); 60 return bytes == null ? null : ByteString.copyFrom(bytes); 61 } 62 63 /** 64 * Deserialize the ByteString into a PersistableBundle. Returns null if failed. 65 */ 66 @Nullable getBundle(ByteString byteString)67 public static PersistableBundle getBundle(ByteString byteString) { 68 byte[] bytes = byteString.toByteArray(); 69 try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes)) { 70 return PersistableBundle.readFromStream(bis); 71 } catch (IOException e) { 72 Slogf.w(CarLog.TAG_TELEMETRY, "Deserializing bytes into PersistableBundle failed.", e); 73 } 74 return null; 75 } 76 77 /** 78 * Reads a PersistableBundle from the given MetricsReportList at the given index. 79 */ 80 @Nullable getBundle(MetricsReportList reportList, int index)81 public static PersistableBundle getBundle(MetricsReportList reportList, int index) { 82 if (index >= reportList.getReportCount()) { 83 return null; 84 } 85 return getBundle(reportList.getReport(index).getReportBytes()); 86 } 87 88 /** 89 * Constructs a MetricsReportList from bundles. All bundles are marked as not the last report. 90 */ 91 @NonNull buildMetricsReportList(PersistableBundle... bundles)92 public static MetricsReportList buildMetricsReportList(PersistableBundle... bundles) { 93 MetricsReportList.Builder reportListBuilder = MetricsReportList.newBuilder(); 94 for (PersistableBundle bundle : bundles) { 95 MetricsReportContainer reportContainer = MetricsReportContainer.newBuilder() 96 .setReportBytes(getByteString(bundle)) 97 .build(); 98 reportListBuilder.addReport(reportContainer); 99 } 100 return reportListBuilder.build(); 101 } 102 } 103