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.appfunctions; 18 19 import static com.android.server.appfunctions.AppFunctionExecutors.LOGGING_THREAD_EXECUTOR; 20 21 import android.annotation.NonNull; 22 import android.app.appfunctions.ExecuteAppFunctionAidlRequest; 23 import android.app.appfunctions.ExecuteAppFunctionResponse; 24 import android.content.Context; 25 import android.content.pm.PackageManager; 26 import android.os.SystemClock; 27 import android.util.Slog; 28 29 import com.android.internal.annotations.VisibleForTesting; 30 31 import java.util.Objects; 32 import java.util.concurrent.Executor; 33 34 /** Wraps AppFunctionsStatsLog. */ 35 public class AppFunctionsLoggerWrapper { 36 private static final String TAG = AppFunctionsLoggerWrapper.class.getSimpleName(); 37 38 @VisibleForTesting static final int SUCCESS_RESPONSE_CODE = -1; 39 40 private final PackageManager mPackageManager; 41 private final Executor mLoggingExecutor; 42 private final AppFunctionsLoggerClock mLoggerClock; 43 AppFunctionsLoggerWrapper(@onNull Context context)44 AppFunctionsLoggerWrapper(@NonNull Context context) { 45 this(context.getPackageManager(), LOGGING_THREAD_EXECUTOR, SystemClock::elapsedRealtime); 46 } 47 48 @VisibleForTesting AppFunctionsLoggerWrapper( @onNull PackageManager packageManager, @NonNull Executor executor, AppFunctionsLoggerClock loggerClock)49 AppFunctionsLoggerWrapper( 50 @NonNull PackageManager packageManager, 51 @NonNull Executor executor, 52 AppFunctionsLoggerClock loggerClock) { 53 mLoggingExecutor = Objects.requireNonNull(executor); 54 mPackageManager = Objects.requireNonNull(packageManager); 55 mLoggerClock = loggerClock; 56 } 57 logAppFunctionSuccess( ExecuteAppFunctionAidlRequest request, ExecuteAppFunctionResponse response, int callingUid, long executionStartTimeMillis)58 void logAppFunctionSuccess( 59 ExecuteAppFunctionAidlRequest request, 60 ExecuteAppFunctionResponse response, 61 int callingUid, 62 long executionStartTimeMillis) { 63 logAppFunctionsRequestReported( 64 request, 65 SUCCESS_RESPONSE_CODE, 66 response.getResponseDataSize(), 67 callingUid, 68 executionStartTimeMillis); 69 } 70 logAppFunctionError( ExecuteAppFunctionAidlRequest request, int errorCode, int callingUid, long executionStartTimeMillis)71 void logAppFunctionError( 72 ExecuteAppFunctionAidlRequest request, 73 int errorCode, 74 int callingUid, 75 long executionStartTimeMillis) { 76 logAppFunctionsRequestReported( 77 request, 78 errorCode, 79 /* responseSizeBytes= */ 0, 80 callingUid, 81 executionStartTimeMillis); 82 } 83 logAppFunctionsRequestReported( ExecuteAppFunctionAidlRequest request, int errorCode, int responseSizeBytes, int callingUid, long executionStartTimeMillis)84 private void logAppFunctionsRequestReported( 85 ExecuteAppFunctionAidlRequest request, 86 int errorCode, 87 int responseSizeBytes, 88 int callingUid, 89 long executionStartTimeMillis) { 90 final long e2eRequestLatencyMillis = 91 mLoggerClock.getCurrentTimeMillis() - request.getRequestTime(); 92 final long requestOverheadMillis = 93 executionStartTimeMillis > 0 94 ? (executionStartTimeMillis - request.getRequestTime()) 95 : e2eRequestLatencyMillis; 96 mLoggingExecutor.execute( 97 () -> 98 AppFunctionsStatsLog.write( 99 AppFunctionsStatsLog.APP_FUNCTIONS_REQUEST_REPORTED, 100 /* callerPackageUid= */ callingUid, 101 /* targetPackageUid= */ getPackageUid( 102 request.getClientRequest().getTargetPackageName()), 103 /* errorCode= */ errorCode, 104 /* requestSizeBytes= */ request.getClientRequest() 105 .getRequestDataSize(), 106 /* responseSizeBytes= */ responseSizeBytes, 107 /* requestDurationMs= */ e2eRequestLatencyMillis, 108 /* requestOverheadMs= */ requestOverheadMillis)); 109 } 110 getPackageUid(String packageName)111 private int getPackageUid(String packageName) { 112 try { 113 return mPackageManager.getPackageUid(packageName, 0); 114 } catch (PackageManager.NameNotFoundException e) { 115 Slog.e(TAG, "Package uid not found for " + packageName); 116 } 117 return 0; 118 } 119 120 /** Wraps a custom clock for easier testing. */ 121 interface AppFunctionsLoggerClock { getCurrentTimeMillis()122 long getCurrentTimeMillis(); 123 } 124 } 125