summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yara Hassan <yaraabdullatif@google.com> 2024-11-29 17:04:00 +0000
committer Yara Hassan <yaraabdullatif@google.com> 2024-12-09 13:17:54 +0000
commit1670d281b339817d114f71cc927850504a973bf9 (patch)
tree7506004c4f8301ffc402162abbfa0d0e122487a2
parente6378dbf40a5973771d3444f0235ca1d2fb71664 (diff)
Log AppFunctionsRequestReported
Flag: android.app.appfunctions.flags.enable_app_function_manager Bug: 376688078 Test: manual test Change-Id: I9e4cdb9d517c6f953f08668d0c89373ffa6b6261
-rw-r--r--core/java/android/app/appfunctions/AppFunctionManager.java4
-rw-r--r--core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java17
-rw-r--r--core/java/android/app/appfunctions/SafeOneTimeExecuteAppFunctionCallback.java27
-rw-r--r--services/appfunctions/Android.bp8
-rw-r--r--services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java7
-rw-r--r--services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java31
-rw-r--r--services/appfunctions/java/com/android/server/appfunctions/AppFunctionsLoggerWrapper.java74
-rw-r--r--services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java2
8 files changed, 159 insertions, 11 deletions
diff --git a/core/java/android/app/appfunctions/AppFunctionManager.java b/core/java/android/app/appfunctions/AppFunctionManager.java
index ed088fed41c2..a731e5085466 100644
--- a/core/java/android/app/appfunctions/AppFunctionManager.java
+++ b/core/java/android/app/appfunctions/AppFunctionManager.java
@@ -34,6 +34,7 @@ import android.os.ICancellationSignal;
import android.os.OutcomeReceiver;
import android.os.ParcelableException;
import android.os.RemoteException;
+import android.os.SystemClock;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -179,7 +180,8 @@ public final class AppFunctionManager {
ExecuteAppFunctionAidlRequest aidlRequest =
new ExecuteAppFunctionAidlRequest(
- request, mContext.getUser(), mContext.getPackageName());
+ request, mContext.getUser(), mContext.getPackageName(),
+ /* requestTime= */ SystemClock.elapsedRealtime());
try {
ICancellationSignal cancellationTransport =
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
index e623fa10f474..707d1fc0473e 100644
--- a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
@@ -41,8 +41,9 @@ public final class ExecuteAppFunctionAidlRequest implements Parcelable {
ExecuteAppFunctionRequest.CREATOR.createFromParcel(in);
UserHandle userHandle = UserHandle.CREATOR.createFromParcel(in);
String callingPackage = in.readString8();
+ long requestTime = in.readLong();
return new ExecuteAppFunctionAidlRequest(
- clientRequest, userHandle, callingPackage);
+ clientRequest, userHandle, callingPackage, requestTime);
}
@Override
@@ -60,11 +61,15 @@ public final class ExecuteAppFunctionAidlRequest implements Parcelable {
/** The package name of the app that is requesting to execute the app function. */
private final String mCallingPackage;
- public ExecuteAppFunctionAidlRequest(
- ExecuteAppFunctionRequest clientRequest, UserHandle userHandle, String callingPackage) {
+ /** The time of calling executeAppFunction(). */
+ private final long mRequestTime;
+
+ public ExecuteAppFunctionAidlRequest(ExecuteAppFunctionRequest clientRequest,
+ UserHandle userHandle, String callingPackage, long requestTime) {
this.mClientRequest = Objects.requireNonNull(clientRequest);
this.mUserHandle = Objects.requireNonNull(userHandle);
this.mCallingPackage = Objects.requireNonNull(callingPackage);
+ this.mRequestTime = requestTime;
}
@Override
@@ -77,6 +82,7 @@ public final class ExecuteAppFunctionAidlRequest implements Parcelable {
mClientRequest.writeToParcel(dest, flags);
mUserHandle.writeToParcel(dest, flags);
dest.writeString8(mCallingPackage);
+ dest.writeLong(mRequestTime);
}
/** Returns the client request to execute an app function. */
@@ -96,4 +102,9 @@ public final class ExecuteAppFunctionAidlRequest implements Parcelable {
public String getCallingPackage() {
return mCallingPackage;
}
+
+ /** Returns the time of calling executeAppFunction(). */
+ public long getRequestTime() {
+ return mRequestTime;
+ }
}
diff --git a/core/java/android/app/appfunctions/SafeOneTimeExecuteAppFunctionCallback.java b/core/java/android/app/appfunctions/SafeOneTimeExecuteAppFunctionCallback.java
index 2426daf5c9f2..e290169bdea8 100644
--- a/core/java/android/app/appfunctions/SafeOneTimeExecuteAppFunctionCallback.java
+++ b/core/java/android/app/appfunctions/SafeOneTimeExecuteAppFunctionCallback.java
@@ -17,6 +17,7 @@
package android.app.appfunctions;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.os.RemoteException;
import android.util.Log;
@@ -37,8 +38,16 @@ public class SafeOneTimeExecuteAppFunctionCallback {
@NonNull private final IExecuteAppFunctionCallback mCallback;
+ @Nullable CompletionCallback mCompletionCallback;
+
public SafeOneTimeExecuteAppFunctionCallback(@NonNull IExecuteAppFunctionCallback callback) {
+ this(callback, /* completionCallback= */ null);
+ }
+
+ public SafeOneTimeExecuteAppFunctionCallback(@NonNull IExecuteAppFunctionCallback callback,
+ @Nullable CompletionCallback completionCallback) {
mCallback = Objects.requireNonNull(callback);
+ mCompletionCallback = completionCallback;
}
/** Invoke wrapped callback with the result. */
@@ -49,6 +58,9 @@ public class SafeOneTimeExecuteAppFunctionCallback {
}
try {
mCallback.onSuccess(result);
+ if (mCompletionCallback != null) {
+ mCompletionCallback.finalizeOnSuccess(result);
+ }
} catch (RemoteException ex) {
// Failed to notify the other end. Ignore.
Log.w(TAG, "Failed to invoke the callback", ex);
@@ -63,6 +75,9 @@ public class SafeOneTimeExecuteAppFunctionCallback {
}
try {
mCallback.onError(error);
+ if (mCompletionCallback != null) {
+ mCompletionCallback.finalizeOnError(error);
+ }
} catch (RemoteException ex) {
// Failed to notify the other end. Ignore.
Log.w(TAG, "Failed to invoke the callback", ex);
@@ -76,4 +91,16 @@ public class SafeOneTimeExecuteAppFunctionCallback {
public void disable() {
mOnResultCalled.set(true);
}
+
+ /**
+ * Provides a hook to execute additional actions after the {@link IExecuteAppFunctionCallback}
+ * has been invoked.
+ */
+ public interface CompletionCallback {
+ /** Called after {@link IExecuteAppFunctionCallback#onSuccess}. */
+ void finalizeOnSuccess(@NonNull ExecuteAppFunctionResponse result);
+
+ /** Called after {@link IExecuteAppFunctionCallback#onError}. */
+ void finalizeOnError(@NonNull AppFunctionException error);
+ }
}
diff --git a/services/appfunctions/Android.bp b/services/appfunctions/Android.bp
index eb6e46861898..7337aa26c145 100644
--- a/services/appfunctions/Android.bp
+++ b/services/appfunctions/Android.bp
@@ -19,6 +19,7 @@ java_library_static {
defaults: ["platform_service_defaults"],
srcs: [
":services.appfunctions-sources",
+ ":statslog-appfunctions-java-gen",
"java/**/*.logtags",
],
libs: ["services.core"],
@@ -26,3 +27,10 @@ java_library_static {
baseline_filename: "lint-baseline.xml",
},
}
+
+genrule {
+ name: "statslog-appfunctions-java-gen",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --java $(out) --module appfunctions --javaPackage com.android.server.appfunctions --javaClass AppFunctionsStatsLog --minApiLevel 35",
+ out: ["java/com/android/server/appfunctions/AppFunctionsStatsLog.java"],
+}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java
index 81e83b563945..eaea4435099c 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java
@@ -16,6 +16,8 @@
package com.android.server.appfunctions;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -35,6 +37,11 @@ public final class AppFunctionExecutors {
/* workQueue= */ new LinkedBlockingQueue<>(),
new NamedThreadFactory("AppFunctionExecutors"));
+ /** Executor for stats logging. */
+ public static final ExecutorService LOGGING_THREAD_EXECUTOR =
+ Executors.newSingleThreadExecutor(
+ new NamedThreadFactory("AppFunctionsLoggingExecutors"));
+
static {
THREAD_POOL_EXECUTOR.allowCoreThreadTimeOut(true);
}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
index c17c34061d1b..9cc5a8c97258 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
@@ -30,6 +30,7 @@ import android.app.appfunctions.AppFunctionManagerHelper;
import android.app.appfunctions.AppFunctionRuntimeMetadata;
import android.app.appfunctions.AppFunctionStaticMetadataHelper;
import android.app.appfunctions.ExecuteAppFunctionAidlRequest;
+import android.app.appfunctions.ExecuteAppFunctionResponse;
import android.app.appfunctions.IAppFunctionEnabledCallback;
import android.app.appfunctions.IAppFunctionManager;
import android.app.appfunctions.IAppFunctionService;
@@ -85,6 +86,7 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
private final ServiceConfig mServiceConfig;
private final Context mContext;
private final Map<String, Object> mLocks = new WeakHashMap<>();
+ private final AppFunctionsLoggerWrapper mLoggerWrapper;
public AppFunctionManagerServiceImpl(@NonNull Context context) {
this(
@@ -93,7 +95,8 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
context, IAppFunctionService.Stub::asInterface, THREAD_POOL_EXECUTOR),
new CallerValidatorImpl(context),
new ServiceHelperImpl(context),
- new ServiceConfigImpl());
+ new ServiceConfigImpl(),
+ new AppFunctionsLoggerWrapper(context));
}
@VisibleForTesting
@@ -102,12 +105,14 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
RemoteServiceCaller<IAppFunctionService> remoteServiceCaller,
CallerValidator callerValidator,
ServiceHelper appFunctionInternalServiceHelper,
- ServiceConfig serviceConfig) {
+ ServiceConfig serviceConfig,
+ AppFunctionsLoggerWrapper loggerWrapper) {
mContext = Objects.requireNonNull(context);
mRemoteServiceCaller = Objects.requireNonNull(remoteServiceCaller);
mCallerValidator = Objects.requireNonNull(callerValidator);
mInternalServiceHelper = Objects.requireNonNull(appFunctionInternalServiceHelper);
mServiceConfig = serviceConfig;
+ mLoggerWrapper = loggerWrapper;
}
/** Called when the user is unlocked. */
@@ -146,8 +151,25 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
Objects.requireNonNull(requestInternal);
Objects.requireNonNull(executeAppFunctionCallback);
+ int callingUid = Binder.getCallingUid();
+ int callingPid = Binder.getCallingPid();
+
final SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback =
- new SafeOneTimeExecuteAppFunctionCallback(executeAppFunctionCallback);
+ new SafeOneTimeExecuteAppFunctionCallback(executeAppFunctionCallback,
+ new SafeOneTimeExecuteAppFunctionCallback.CompletionCallback() {
+ @Override
+ public void finalizeOnSuccess(
+ @NonNull ExecuteAppFunctionResponse result) {
+ mLoggerWrapper.logAppFunctionSuccess(requestInternal, result,
+ callingUid);
+ }
+
+ @Override
+ public void finalizeOnError(@NonNull AppFunctionException error) {
+ mLoggerWrapper.logAppFunctionError(requestInternal,
+ error.getErrorCode(), callingUid);
+ }
+ });
String validatedCallingPackage;
try {
@@ -162,9 +184,6 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
return null;
}
- int callingUid = Binder.getCallingUid();
- int callingPid = Binder.getCallingPid();
-
ICancellationSignal localCancelTransport = CancellationSignal.createTransport();
THREAD_POOL_EXECUTOR.execute(
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionsLoggerWrapper.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionsLoggerWrapper.java
new file mode 100644
index 000000000000..b59915aa6343
--- /dev/null
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionsLoggerWrapper.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appfunctions;
+
+import static com.android.server.appfunctions.AppFunctionExecutors.LOGGING_THREAD_EXECUTOR;
+
+import android.annotation.NonNull;
+import android.app.appfunctions.ExecuteAppFunctionAidlRequest;
+import android.app.appfunctions.ExecuteAppFunctionResponse;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
+import android.util.Slog;
+
+import java.util.Objects;
+
+/** Wraps AppFunctionsStatsLog. */
+public class AppFunctionsLoggerWrapper {
+ private static final String TAG = AppFunctionsLoggerWrapper.class.getSimpleName();
+
+ private static final int SUCCESS_RESPONSE_CODE = -1;
+
+ private final Context mContext;
+
+ public AppFunctionsLoggerWrapper(@NonNull Context context) {
+ mContext = Objects.requireNonNull(context);
+ }
+
+ void logAppFunctionSuccess(ExecuteAppFunctionAidlRequest request,
+ ExecuteAppFunctionResponse response, int callingUid) {
+ logAppFunctionsRequestReported(request, SUCCESS_RESPONSE_CODE,
+ response.getResponseDataSize(), callingUid);
+ }
+
+ void logAppFunctionError(ExecuteAppFunctionAidlRequest request, int errorCode, int callingUid) {
+ logAppFunctionsRequestReported(request, errorCode, /* responseSizeBytes = */ 0, callingUid);
+ }
+
+ private void logAppFunctionsRequestReported(ExecuteAppFunctionAidlRequest request,
+ int errorCode, int responseSizeBytes, int callingUid) {
+ final long latency = SystemClock.elapsedRealtime() - request.getRequestTime();
+ LOGGING_THREAD_EXECUTOR.execute(() -> AppFunctionsStatsLog.write(
+ AppFunctionsStatsLog.APP_FUNCTIONS_REQUEST_REPORTED,
+ callingUid,
+ getPackageUid(request.getClientRequest().getTargetPackageName()),
+ errorCode,
+ request.getClientRequest().getRequestDataSize(), responseSizeBytes,
+ latency)
+ );
+ }
+
+ private int getPackageUid(String packageName) {
+ try {
+ return mContext.getPackageManager().getPackageUid(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "Package uid not found for " + packageName);
+ }
+ return 0;
+ }
+}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
index c689bb92f8f7..896c0fc51683 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
@@ -16,8 +16,8 @@
package com.android.server.appfunctions;
import android.annotation.NonNull;
-import android.app.appfunctions.ExecuteAppFunctionAidlRequest;
import android.app.appfunctions.AppFunctionException;
+import android.app.appfunctions.ExecuteAppFunctionAidlRequest;
import android.app.appfunctions.ExecuteAppFunctionResponse;
import android.app.appfunctions.IAppFunctionService;
import android.app.appfunctions.ICancellationCallback;