1 /* 2 * Copyright (C) 2024 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 android.app.sdksandbox.SandboxLatencyInfo.RESULT_CODE_LOAD_SDK_ALREADY_LOADED; 20 import static android.app.sdksandbox.SandboxLatencyInfo.RESULT_CODE_LOAD_SDK_INTERNAL_ERROR; 21 import static android.app.sdksandbox.SandboxLatencyInfo.RESULT_CODE_LOAD_SDK_NOT_FOUND; 22 import static android.app.sdksandbox.SandboxLatencyInfo.RESULT_CODE_LOAD_SDK_SDK_DEFINED_ERROR; 23 import static android.app.sdksandbox.SandboxLatencyInfo.RESULT_CODE_LOAD_SDK_SDK_SANDBOX_DISABLED; 24 import static android.app.sdksandbox.SandboxLatencyInfo.RESULT_CODE_SDK_SANDBOX_PROCESS_NOT_AVAILABLE; 25 26 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_ALREADY_LOADED; 27 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_INTERNAL_ERROR; 28 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_NOT_FOUND; 29 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_SDK_DEFINED_ERROR; 30 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_SDK_SANDBOX_DISABLED; 31 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__RESULT_CODE__RESULT_CODE_UNSPECIFIED; 32 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__RESULT_CODE__SDK_SANDBOX_PROCESS_NOT_AVAILABLE; 33 34 import android.app.sdksandbox.SandboxLatencyInfo; 35 import android.os.Binder; 36 import android.util.Log; 37 38 import com.android.sdksandbox.service.stats.SdkSandboxStatsLog; 39 40 /** 41 * Helper class to handle StatsD metrics logging logic. 42 * 43 * @hide 44 */ 45 class SdkSandboxStatsdLogger { 46 private static final String TAG = SdkSandboxStatsdLogger.class.getSimpleName(); 47 48 /** 49 * Send sandbox API call latency data to StatsD. Corresponding StatsD atom is SandboxApiCalled. 50 */ logSandboxApiLatency(SandboxLatencyInfo sandboxLatencyInfo)51 public void logSandboxApiLatency(SandboxLatencyInfo sandboxLatencyInfo) { 52 int method = convertToStatsLogMethodCode(sandboxLatencyInfo.getMethod()); 53 if (method == SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__METHOD_UNSPECIFIED) { 54 Log.w(TAG, "Not logging sandbox API latency for unspecified method"); 55 return; 56 } 57 int resultCode = convertToStatsLogResultCode(sandboxLatencyInfo.getResultCode()); 58 int callingUid = Binder.getCallingUid(); 59 60 logSandboxApiLatencyForStage( 61 method, 62 sandboxLatencyInfo.getAppToSystemServerLatency(), 63 sandboxLatencyInfo.isSuccessfulAtAppToSystemServer(), 64 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER, 65 callingUid, 66 resultCode); 67 logSandboxApiLatencyForStage( 68 method, 69 sandboxLatencyInfo.getSystemServerAppToSandboxLatency(), 70 sandboxLatencyInfo.isSuccessfulAtSystemServerAppToSandbox(), 71 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, 72 callingUid, 73 resultCode); 74 logSandboxApiLatencyForStage( 75 method, 76 sandboxLatencyInfo.getLoadSandboxLatency(), 77 sandboxLatencyInfo.isSuccessfulAtLoadSandbox(), 78 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__LOAD_SANDBOX, 79 callingUid, 80 resultCode); 81 logSandboxApiLatencyForStage( 82 method, 83 sandboxLatencyInfo.getSystemServerToSandboxLatency(), 84 sandboxLatencyInfo.isSuccessfulAtSystemServerToSandbox(), 85 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX, 86 callingUid, 87 resultCode); 88 logSandboxApiLatencyForStage( 89 method, 90 sandboxLatencyInfo.getSandboxLatency(), 91 sandboxLatencyInfo.isSuccessfulAtSandbox(), 92 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX, 93 callingUid, 94 resultCode); 95 logSandboxApiLatencyForStage( 96 method, 97 sandboxLatencyInfo.getSdkLatency(), 98 sandboxLatencyInfo.isSuccessfulAtSdk(), 99 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SDK, 100 callingUid, 101 resultCode); 102 logSandboxApiLatencyForStage( 103 method, 104 sandboxLatencyInfo.getSandboxToSystemServerLatency(), 105 sandboxLatencyInfo.isSuccessfulAtSandboxToSystemServer(), 106 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER, 107 callingUid, 108 resultCode); 109 logSandboxApiLatencyForStage( 110 method, 111 sandboxLatencyInfo.getSystemServerSandboxToAppLatency(), 112 sandboxLatencyInfo.isSuccessfulAtSystemServerSandboxToApp(), 113 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP, 114 callingUid, 115 resultCode); 116 logSandboxApiLatencyForStage( 117 method, 118 sandboxLatencyInfo.getSystemServerToAppLatency(), 119 sandboxLatencyInfo.isSuccessfulAtSystemServerToApp(), 120 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_APP, 121 callingUid, 122 resultCode); 123 124 int totalCallStage = SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__TOTAL; 125 if (method == SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK 126 && sandboxLatencyInfo.getLoadSandboxLatency() != -1) { 127 totalCallStage = SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__TOTAL_WITH_LOAD_SANDBOX; 128 } 129 logSandboxApiLatencyForStage( 130 method, 131 sandboxLatencyInfo.getTotalCallLatency(), 132 sandboxLatencyInfo.isTotalCallSuccessful(), 133 totalCallStage, 134 callingUid, 135 resultCode); 136 } 137 convertToStatsLogMethodCode(int method)138 private int convertToStatsLogMethodCode(int method) { 139 return switch (method) { 140 case SandboxLatencyInfo.METHOD_LOAD_SDK -> 141 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK; 142 case SandboxLatencyInfo.METHOD_LOAD_SDK_VIA_CONTROLLER -> 143 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK_VIA_CONTROLLER; 144 case SandboxLatencyInfo.METHOD_GET_SANDBOXED_SDKS -> 145 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__GET_SANDBOXED_SDKS; 146 case SandboxLatencyInfo.METHOD_GET_SANDBOXED_SDKS_VIA_CONTROLLER -> 147 SdkSandboxStatsLog 148 .SANDBOX_API_CALLED__METHOD__GET_SANDBOXED_SDKS_VIA_CONTROLLER; 149 case SandboxLatencyInfo.METHOD_SYNC_DATA_FROM_CLIENT -> 150 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__SYNC_DATA_FROM_CLIENT; 151 case SandboxLatencyInfo.METHOD_REQUEST_SURFACE_PACKAGE -> 152 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE; 153 case SandboxLatencyInfo.METHOD_REGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE -> 154 SdkSandboxStatsLog 155 .SANDBOX_API_CALLED__METHOD__REGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE; 156 case SandboxLatencyInfo.METHOD_UNREGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE -> 157 SdkSandboxStatsLog 158 .SANDBOX_API_CALLED__METHOD__UNREGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE; 159 case SandboxLatencyInfo.METHOD_GET_APP_OWNED_SDK_SANDBOX_INTERFACES -> 160 SdkSandboxStatsLog 161 .SANDBOX_API_CALLED__METHOD__GET_APP_OWNED_SDK_SANDBOX_INTERFACES; 162 case SandboxLatencyInfo.METHOD_UNLOAD_SDK -> 163 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__UNLOAD_SDK; 164 case SandboxLatencyInfo.METHOD_ADD_SDK_SANDBOX_LIFECYCLE_CALLBACK -> 165 SdkSandboxStatsLog 166 .SANDBOX_API_CALLED__METHOD__ADD_SDK_SANDBOX_LIFECYCLE_CALLBACK; 167 case SandboxLatencyInfo.METHOD_REMOVE_SDK_SANDBOX_LIFECYCLE_CALLBACK -> 168 SdkSandboxStatsLog 169 .SANDBOX_API_CALLED__METHOD__REMOVE_SDK_SANDBOX_LIFECYCLE_CALLBACK; 170 default -> SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__METHOD_UNSPECIFIED; 171 }; 172 } 173 convertToStatsLogResultCode(@andboxLatencyInfo.ResultCode int resultCode)174 private int convertToStatsLogResultCode(@SandboxLatencyInfo.ResultCode int resultCode) { 175 return switch (resultCode) { 176 case RESULT_CODE_LOAD_SDK_NOT_FOUND -> 177 SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_NOT_FOUND; 178 case RESULT_CODE_LOAD_SDK_ALREADY_LOADED -> 179 SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_ALREADY_LOADED; 180 case RESULT_CODE_LOAD_SDK_SDK_DEFINED_ERROR -> 181 SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_SDK_DEFINED_ERROR; 182 case RESULT_CODE_LOAD_SDK_SDK_SANDBOX_DISABLED -> 183 SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_SDK_SANDBOX_DISABLED; 184 case RESULT_CODE_LOAD_SDK_INTERNAL_ERROR -> 185 SANDBOX_API_CALLED__RESULT_CODE__LOAD_SDK_INTERNAL_ERROR; 186 case RESULT_CODE_SDK_SANDBOX_PROCESS_NOT_AVAILABLE -> 187 SANDBOX_API_CALLED__RESULT_CODE__SDK_SANDBOX_PROCESS_NOT_AVAILABLE; 188 default -> SANDBOX_API_CALLED__RESULT_CODE__RESULT_CODE_UNSPECIFIED; 189 }; 190 } 191 192 private void logSandboxApiLatencyForStage( 193 int method, int latency, boolean success, int stage, int callingUid, int resultCode) { 194 if (latency != -1) { 195 SdkSandboxStatsLog.write( 196 SdkSandboxStatsLog.SANDBOX_API_CALLED, 197 method, 198 latency, 199 success, 200 stage, 201 callingUid, 202 resultCode); 203 } 204 } 205 206 /** 207 * Send sandbox activity API call latency data to StatsD. Corresponding StatsD atom is 208 * SandboxActivityEventOccurred. 209 */ 210 public void logSandboxActivityApiLatency( 211 int method, int callResult, int latencyMillis, int clientUid) { 212 SdkSandboxStatsLog.write( 213 SdkSandboxStatsLog.SANDBOX_ACTIVITY_EVENT_OCCURRED, 214 method, 215 callResult, 216 latencyMillis, 217 clientUid, 218 /*sdkUid=*/ -1); 219 } 220 } 221