1 /* 2 * Copyright (C) 2019 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.stats; 18 19 import android.annotation.Nullable; 20 import android.car.vms.VmsLayer; 21 import android.util.ArrayMap; 22 import android.util.StatsLog; 23 24 import com.android.internal.annotations.GuardedBy; 25 26 import java.util.Collection; 27 import java.util.Map; 28 import java.util.concurrent.atomic.AtomicLong; 29 import java.util.stream.Collectors; 30 31 /** 32 * Logger for per-client VMS statistics. 33 */ 34 public class VmsClientLogger { 35 /** 36 * Constants used for identifying client connection states. 37 */ 38 public static class ConnectionState { 39 // Attempting to connect to the client 40 public static final int CONNECTING = 41 StatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED__STATE__CONNECTING; 42 // Client connection established 43 public static final int CONNECTED = 44 StatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED__STATE__CONNECTED; 45 // Client connection closed unexpectedly 46 public static final int DISCONNECTED = 47 StatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED__STATE__DISCONNECTED; 48 // Client connection closed by VMS 49 public static final int TERMINATED = 50 StatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED__STATE__TERMINATED; 51 // Error establishing the client connection 52 public static final int CONNECTION_ERROR = 53 StatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED__STATE__CONNECTION_ERROR; 54 } 55 56 private final Object mLock = new Object(); 57 58 private final int mUid; 59 private final String mPackageName; 60 61 @GuardedBy("mLock") 62 private Map<Integer, AtomicLong> mConnectionStateCounters = new ArrayMap<>(); 63 64 @GuardedBy("mLock") 65 private final Map<VmsLayer, VmsClientStats> mLayerStats = new ArrayMap<>(); 66 VmsClientLogger(int clientUid, @Nullable String clientPackage)67 VmsClientLogger(int clientUid, @Nullable String clientPackage) { 68 mUid = clientUid; 69 mPackageName = clientPackage != null ? clientPackage : ""; 70 } 71 getUid()72 public int getUid() { 73 return mUid; 74 } 75 getPackageName()76 public String getPackageName() { 77 return mPackageName; 78 } 79 80 /** 81 * Logs a connection state change for the client. 82 * 83 * @param connectionState New connection state 84 */ logConnectionState(int connectionState)85 public void logConnectionState(int connectionState) { 86 StatsLog.write(StatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED, 87 mUid, mPackageName, connectionState); 88 89 AtomicLong counter; 90 synchronized (mLock) { 91 counter = mConnectionStateCounters.computeIfAbsent(connectionState, 92 ignored -> new AtomicLong()); 93 } 94 counter.incrementAndGet(); 95 } 96 getConnectionStateCount(int connectionState)97 long getConnectionStateCount(int connectionState) { 98 AtomicLong counter; 99 synchronized (mLock) { 100 counter = mConnectionStateCounters.get(connectionState); 101 } 102 return counter == null ? 0L : counter.get(); 103 } 104 105 /** 106 * Logs that a packet was published by the client. 107 * 108 * @param layer Layer of packet 109 * @param size Size of packet 110 */ logPacketSent(VmsLayer layer, long size)111 public void logPacketSent(VmsLayer layer, long size) { 112 getLayerEntry(layer).packetSent(size); 113 } 114 115 /** 116 * Logs that a packet was received successfully by the client. 117 * 118 * @param layer Layer of packet 119 * @param size Size of packet 120 */ logPacketReceived(VmsLayer layer, long size)121 public void logPacketReceived(VmsLayer layer, long size) { 122 getLayerEntry(layer).packetReceived(size); 123 } 124 125 /** 126 * Logs that a packet was dropped due to an error delivering to the client. 127 * 128 * @param layer Layer of packet 129 * @param size Size of packet 130 */ logPacketDropped(VmsLayer layer, long size)131 public void logPacketDropped(VmsLayer layer, long size) { 132 getLayerEntry(layer).packetDropped(size); 133 } 134 getLayerEntries()135 Collection<VmsClientStats> getLayerEntries() { 136 synchronized (mLock) { 137 return mLayerStats.values().stream() 138 .map(VmsClientStats::new) // Make a deep copy of the entries 139 .collect(Collectors.toList()); 140 } 141 } 142 getLayerEntry(VmsLayer layer)143 private VmsClientStats getLayerEntry(VmsLayer layer) { 144 synchronized (mLock) { 145 return mLayerStats.computeIfAbsent( 146 layer, 147 (k) -> new VmsClientStats(mUid, layer)); 148 } 149 } 150 } 151