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 static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_SDK_STORAGE; 20 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.buildStatsEvent; 21 import static com.android.server.sdksandbox.SandboxesStorageMetrics.StorageStatsEvent; 22 23 import android.app.StatsManager; 24 import android.content.Context; 25 import android.util.Log; 26 import android.util.StatsEvent; 27 28 import com.android.internal.annotations.GuardedBy; 29 import com.android.modules.utils.BackgroundThread; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 34 /** 35 * A class to initialize and log metrics which will be pulled by StatsD 36 * 37 * @hide 38 */ 39 public class SdkSandboxPulledAtoms { 40 41 private static final String TAG = "SdkSandboxManager"; 42 private final Object mLock = new Object(); 43 44 @GuardedBy("mLock") 45 private boolean mInitialized = false; 46 47 private final SandboxesStorageMetrics mSandboxesStorageMetrics = new SandboxesStorageMetrics(); 48 49 /** Initializes the callback which will be called from StatsD */ initialize(Context context)50 public void initialize(Context context) { 51 synchronized (mLock) { 52 if (mInitialized) { 53 return; 54 } 55 final StatsManager statsManager = context.getSystemService(StatsManager.class); 56 if (statsManager == null) { 57 Log.e(TAG, "Error retrieving StatsManager. Cannot initialize PulledMetrics."); 58 return; 59 } 60 Log.d(TAG, "Registering callback with StatsManager"); 61 62 try { 63 // Callback handler for registering for SDK storage atom 64 statsManager.setPullAtomCallback( 65 SANDBOX_SDK_STORAGE, 66 /*metadata=*/ null, 67 BackgroundThread.getExecutor(), 68 /** 69 * Class which implements the callback method which will be called by StatsD 70 */ 71 (atomTag, data) -> { 72 if (atomTag != SANDBOX_SDK_STORAGE) { 73 Log.e(TAG, "Incorrect atomTag for SandboxSdkStorage"); 74 return StatsManager.PULL_SKIP; 75 } 76 77 final List<StatsEvent> events = new ArrayList<>(); 78 for (StorageStatsEvent sandboxStorageStatsEvent : 79 mSandboxesStorageMetrics.consumeStorageStatsEvents()) { 80 events.add( 81 buildStatsEvent( 82 SANDBOX_SDK_STORAGE, 83 sandboxStorageStatsEvent.mShared, 84 sandboxStorageStatsEvent.mStorageKb, 85 sandboxStorageStatsEvent.mUid)); 86 } 87 if (events == null) { 88 return StatsManager.PULL_SKIP; 89 } 90 91 data.addAll(events); 92 return StatsManager.PULL_SUCCESS; 93 }); 94 mInitialized = true; 95 } catch (NullPointerException e) { 96 Log.w(TAG, "Pulled metrics not supported. Could not register.", e); 97 } 98 } 99 } 100 101 /** 102 * Logs the storage information of SDKs in memory which will later be pulled by StatsD callback 103 */ logStorage(int uid, int sharedStorageKb, int sdkStorageKb)104 public void logStorage(int uid, int sharedStorageKb, int sdkStorageKb) { 105 mSandboxesStorageMetrics.log(uid, sharedStorageKb, sdkStorageKb); 106 } 107 } 108