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.SparseArray; 23 24 import com.android.car.CarStatsLog; 25 import com.android.internal.annotations.GuardedBy; 26 27 import java.util.ArrayList; 28 import java.util.Collection; 29 import java.util.concurrent.atomic.AtomicLong; 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 CarStatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED__STATE__CONNECTING; 42 // Client connection established 43 public static final int CONNECTED = 44 CarStatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED__STATE__CONNECTED; 45 // Client connection closed unexpectedly 46 public static final int DISCONNECTED = 47 CarStatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED__STATE__DISCONNECTED; 48 // Client connection closed by VMS 49 public static final int TERMINATED = 50 CarStatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED__STATE__TERMINATED; 51 // Error establishing the client connection 52 public static final int CONNECTION_ERROR = 53 CarStatsLog.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 SparseArray<AtomicLong> mConnectionStateCounters = new SparseArray<>(); 63 64 @GuardedBy("mLock") 65 private final ArrayMap<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 CarStatsLog.write(CarStatsLog.VMS_CLIENT_CONNECTION_STATE_CHANGED, 87 mUid, connectionState); 88 89 AtomicLong counter; 90 synchronized (mLock) { 91 if (!mConnectionStateCounters.contains(connectionState)) { 92 mConnectionStateCounters.put(connectionState, new AtomicLong()); 93 } 94 counter = mConnectionStateCounters.get(connectionState); 95 } 96 counter.incrementAndGet(); 97 } 98 getConnectionStateCount(int connectionState)99 long getConnectionStateCount(int connectionState) { 100 AtomicLong counter; 101 synchronized (mLock) { 102 counter = mConnectionStateCounters.get(connectionState); 103 } 104 return counter == null ? 0L : counter.get(); 105 } 106 107 /** 108 * Logs that a packet was published by the client. 109 * 110 * @param layer Layer of packet 111 * @param size Size of packet 112 */ logPacketSent(VmsLayer layer, long size)113 public void logPacketSent(VmsLayer layer, long size) { 114 getLayerEntry(layer).packetSent(size); 115 } 116 117 /** 118 * Logs that a packet was received successfully by the client. 119 * 120 * @param layer Layer of packet 121 * @param size Size of packet 122 */ logPacketReceived(VmsLayer layer, long size)123 public void logPacketReceived(VmsLayer layer, long size) { 124 getLayerEntry(layer).packetReceived(size); 125 } 126 127 /** 128 * Logs that a packet was dropped due to an error delivering to the client. 129 * 130 * @param layer Layer of packet 131 * @param size Size of packet 132 */ logPacketDropped(VmsLayer layer, long size)133 public void logPacketDropped(VmsLayer layer, long size) { 134 getLayerEntry(layer).packetDropped(size); 135 } 136 getLayerEntries()137 Collection<VmsClientStats> getLayerEntries() { 138 synchronized (mLock) { 139 ArrayList<VmsClientStats> layerEntries = new ArrayList<>(mLayerStats.size()); 140 for (int index = 0; index < mLayerStats.size(); index++) { 141 layerEntries.add(new VmsClientStats(mLayerStats.valueAt(index))); 142 } 143 return layerEntries; 144 } 145 } 146 getLayerEntry(VmsLayer layer)147 private VmsClientStats getLayerEntry(VmsLayer layer) { 148 synchronized (mLock) { 149 return mLayerStats.computeIfAbsent( 150 layer, 151 (k) -> new VmsClientStats(mUid, layer)); 152 } 153 } 154 } 155