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.server.sdksandbox; 18 19 import android.util.SparseArray; 20 21 import com.android.internal.annotations.GuardedBy; 22 23 import java.util.ArrayList; 24 import java.util.List; 25 import java.util.Objects; 26 27 /** 28 * Class for methods used to store and fetch SDK storage information 29 * 30 * @hide 31 */ 32 public class SandboxesStorageMetrics { 33 private static final int MAX_ENTRIES_PER_UID = 5; 34 public final Object mLock = new Object(); 35 36 @GuardedBy("mLock") 37 public final SparseArray<List<SandboxMetrics>> mMetrics = new SparseArray<>(); 38 39 /** Store SDK storage info for UID */ log(int uid, int sharedStorageKb, int sdkStorageKb)40 public void log(int uid, int sharedStorageKb, int sdkStorageKb) { 41 List<SandboxMetrics> sandboxMetrics; 42 synchronized (mLock) { 43 sandboxMetrics = mMetrics.get(uid); 44 if (sandboxMetrics == null) { 45 sandboxMetrics = new ArrayList<>(); 46 mMetrics.append(uid, sandboxMetrics); 47 } 48 sandboxMetrics.add(new SandboxMetrics(sharedStorageKb, sdkStorageKb)); 49 } 50 51 /** 52 * If there are more metrics data points than we want, we remove the one that was added at 53 * the beginning of the list. 54 */ 55 if (sandboxMetrics.size() > MAX_ENTRIES_PER_UID) { 56 sandboxMetrics.remove(0); 57 } 58 } 59 60 /** Class to store the private and shared metrics from a single log of a single sandbox. */ 61 private static class SandboxMetrics { 62 public int mSharedKb; 63 public int mPrivateKb; 64 SandboxMetrics(int sharedKb, int privateKb)65 SandboxMetrics(int sharedKb, int privateKb) { 66 mSharedKb = sharedKb; 67 mPrivateKb = privateKb; 68 } 69 } 70 71 /** Collects the SDK storage metrics information into an object */ consumeStorageStatsEvents()72 public List<StorageStatsEvent> consumeStorageStatsEvents() { 73 List<StorageStatsEvent> sandboxStorageStatsEvents = new ArrayList<>(); 74 synchronized (mLock) { 75 final int metricsSize = mMetrics.size(); 76 for (int i = 0; i < metricsSize; i++) { 77 final List<SandboxMetrics> sandboxMetrics = mMetrics.valueAt(i); 78 79 for (SandboxMetrics sandboxMetric : sandboxMetrics) { 80 sandboxStorageStatsEvents.add( 81 new StorageStatsEvent( 82 /*shared=*/ true, sandboxMetric.mSharedKb, mMetrics.keyAt(i))); 83 sandboxStorageStatsEvents.add( 84 new StorageStatsEvent( 85 /*shared=*/ false, 86 sandboxMetric.mPrivateKb, 87 mMetrics.keyAt(i))); 88 } 89 } 90 mMetrics.clear(); 91 return sandboxStorageStatsEvents; 92 } 93 } 94 95 /** Class to store the parameters of buildStatsEvent for SANDBOX_SDK_STORAGE. */ 96 static class StorageStatsEvent { 97 public boolean mShared; 98 public int mStorageKb; 99 public int mUid; 100 StorageStatsEvent(boolean shared, int storageKb, int uid)101 StorageStatsEvent(boolean shared, int storageKb, int uid) { 102 mShared = shared; 103 mStorageKb = storageKb; 104 mUid = uid; 105 } 106 107 @Override equals(Object o)108 public boolean equals(Object o) { 109 if (this == o) return true; 110 if (!(o instanceof StorageStatsEvent)) return false; 111 StorageStatsEvent that = (StorageStatsEvent) o; 112 return mShared == that.mShared && mStorageKb == that.mStorageKb && mUid == that.mUid; 113 } 114 115 @Override hashCode()116 public int hashCode() { 117 return Objects.hash(mShared, mStorageKb, mUid); 118 } 119 } 120 } 121