summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt2
-rw-r--r--core/java/android/app/appfunctions/AppFunctionService.java32
-rw-r--r--core/java/android/app/appfunctions/IAppFunctionService.aidl3
-rw-r--r--core/java/android/content/pm/SigningInfo.aidl19
-rw-r--r--libs/appfunctions/api/current.txt3
-rw-r--r--libs/appfunctions/java/com/android/extensions/appfunctions/AppFunctionService.java67
-rw-r--r--services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java32
-rw-r--r--services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java13
8 files changed, 138 insertions, 33 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index c4109392d6bd..6707c15de682 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8905,7 +8905,7 @@ package android.app.appfunctions {
@FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public abstract class AppFunctionService extends android.app.Service {
ctor public AppFunctionService();
method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent);
- method @MainThread public abstract void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull String, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.app.appfunctions.ExecuteAppFunctionResponse,android.app.appfunctions.AppFunctionException>);
+ method @MainThread public abstract void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull String, @NonNull android.content.pm.SigningInfo, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.app.appfunctions.ExecuteAppFunctionResponse,android.app.appfunctions.AppFunctionException>);
field @NonNull public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService";
}
diff --git a/core/java/android/app/appfunctions/AppFunctionService.java b/core/java/android/app/appfunctions/AppFunctionService.java
index d86f1d841d33..8e48b4e56570 100644
--- a/core/java/android/app/appfunctions/AppFunctionService.java
+++ b/core/java/android/app/appfunctions/AppFunctionService.java
@@ -28,6 +28,7 @@ import android.annotation.SdkConstant;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.SigningInfo;
import android.os.Binder;
import android.os.CancellationSignal;
import android.os.IBinder;
@@ -78,10 +79,10 @@ public abstract class AppFunctionService extends Service {
void perform(
@NonNull ExecuteAppFunctionRequest request,
@NonNull String callingPackage,
+ @NonNull SigningInfo callingPackageSigningInfo,
@NonNull CancellationSignal cancellationSignal,
@NonNull
- OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException>
- callback);
+ OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException> callback);
}
/** @hide */
@@ -93,6 +94,7 @@ public abstract class AppFunctionService extends Service {
public void executeAppFunction(
@NonNull ExecuteAppFunctionRequest request,
@NonNull String callingPackage,
+ @NonNull SigningInfo callingPackageSigningInfo,
@NonNull ICancellationCallback cancellationCallback,
@NonNull IExecuteAppFunctionCallback callback) {
if (context.checkCallingPermission(BIND_APP_FUNCTION_SERVICE)
@@ -105,6 +107,7 @@ public abstract class AppFunctionService extends Service {
onExecuteFunction.perform(
request,
callingPackage,
+ callingPackageSigningInfo,
buildCancellationSignal(cancellationCallback),
new OutcomeReceiver<>() {
@Override
@@ -154,15 +157,17 @@ public abstract class AppFunctionService extends Service {
/**
* Called by the system to execute a specific app function.
*
- * <p>This method is triggered when the system requests your AppFunctionService to handle a
- * particular function you have registered and made available.
+ * <p>This method is the entry point for handling all app function requests in an app. When the
+ * system needs your AppFunctionService to perform a function, it will invoke this method.
*
- * <p>To ensure proper routing of function requests, assign a unique identifier to each
- * function. This identifier doesn't need to be globally unique, but it must be unique within
- * your app. For example, a function to order food could be identified as "orderFood". In most
- * cases this identifier should come from the ID automatically generated by the AppFunctions
- * SDK. You can determine the specific function to invoke by calling {@link
- * ExecuteAppFunctionRequest#getFunctionIdentifier()}.
+ * <p>Each function you've registered is identified by a unique identifier. This identifier
+ * doesn't need to be globally unique, but it must be unique within your app. For example, a
+ * function to order food could be identified as "orderFood". In most cases, this identifier is
+ * automatically generated by the AppFunctions SDK.
+ *
+ * <p>You can determine which function to execute by calling {@link
+ * ExecuteAppFunctionRequest#getFunctionIdentifier()}. This allows your service to route the
+ * incoming request to the appropriate logic for handling the specific function.
*
* <p>This method is always triggered in the main thread. You should run heavy tasks on a worker
* thread and dispatch the result with the given callback. You should always report back the
@@ -173,6 +178,8 @@ public abstract class AppFunctionService extends Service {
*
* @param request The function execution request.
* @param callingPackage The package name of the app that is requesting the execution.
+ * @param callingPackageSigningInfo The signing information of the app that is requesting the
+ * execution.
* @param cancellationSignal A signal to cancel the execution.
* @param callback A callback to report back the result or error.
*/
@@ -180,10 +187,9 @@ public abstract class AppFunctionService extends Service {
public abstract void onExecuteFunction(
@NonNull ExecuteAppFunctionRequest request,
@NonNull String callingPackage,
+ @NonNull SigningInfo callingPackageSigningInfo,
@NonNull CancellationSignal cancellationSignal,
- @NonNull
- OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException>
- callback);
+ @NonNull OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException> callback);
/**
* Returns result codes from throwable.
diff --git a/core/java/android/app/appfunctions/IAppFunctionService.aidl b/core/java/android/app/appfunctions/IAppFunctionService.aidl
index bf935d2a102b..78bcb7f66eb1 100644
--- a/core/java/android/app/appfunctions/IAppFunctionService.aidl
+++ b/core/java/android/app/appfunctions/IAppFunctionService.aidl
@@ -35,12 +35,15 @@ oneway interface IAppFunctionService {
*
* @param request the function execution request.
* @param callingPackage The package name of the app that is requesting the execution.
+ * @param callingPackageSigningInfo The signing information of the app that is requesting the
+ * execution.
* @param cancellationCallback a callback to send back the cancellation transport.
* @param callback a callback to report back the result.
*/
void executeAppFunction(
in ExecuteAppFunctionRequest request,
in String callingPackage,
+ in android.content.pm.SigningInfo callingPackageSigningInfo,
in ICancellationCallback cancellationCallback,
in IExecuteAppFunctionCallback callback
);
diff --git a/core/java/android/content/pm/SigningInfo.aidl b/core/java/android/content/pm/SigningInfo.aidl
new file mode 100644
index 000000000000..bc986d1b214b
--- /dev/null
+++ b/core/java/android/content/pm/SigningInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.content.pm;
+
+parcelable SigningInfo; \ No newline at end of file
diff --git a/libs/appfunctions/api/current.txt b/libs/appfunctions/api/current.txt
index 139ccfd22b0e..f8fb6b7207a0 100644
--- a/libs/appfunctions/api/current.txt
+++ b/libs/appfunctions/api/current.txt
@@ -36,7 +36,8 @@ package com.android.extensions.appfunctions {
public abstract class AppFunctionService extends android.app.Service {
ctor public AppFunctionService();
method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent);
- method @MainThread public abstract void onExecuteFunction(@NonNull com.android.extensions.appfunctions.ExecuteAppFunctionRequest, @NonNull String, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<com.android.extensions.appfunctions.ExecuteAppFunctionResponse,com.android.extensions.appfunctions.AppFunctionException>);
+ method @MainThread public void onExecuteFunction(@NonNull com.android.extensions.appfunctions.ExecuteAppFunctionRequest, @NonNull String, @NonNull android.content.pm.SigningInfo, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<com.android.extensions.appfunctions.ExecuteAppFunctionResponse,com.android.extensions.appfunctions.AppFunctionException>);
+ method @Deprecated @MainThread public abstract void onExecuteFunction(@NonNull com.android.extensions.appfunctions.ExecuteAppFunctionRequest, @NonNull String, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<com.android.extensions.appfunctions.ExecuteAppFunctionResponse,com.android.extensions.appfunctions.AppFunctionException>);
field @NonNull public static final String BIND_APP_FUNCTION_SERVICE = "android.permission.BIND_APP_FUNCTION_SERVICE";
field @NonNull public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService";
}
diff --git a/libs/appfunctions/java/com/android/extensions/appfunctions/AppFunctionService.java b/libs/appfunctions/java/com/android/extensions/appfunctions/AppFunctionService.java
index 9f3c34575b94..a09451ede4fc 100644
--- a/libs/appfunctions/java/com/android/extensions/appfunctions/AppFunctionService.java
+++ b/libs/appfunctions/java/com/android/extensions/appfunctions/AppFunctionService.java
@@ -25,6 +25,7 @@ import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.app.Service;
import android.content.Intent;
+import android.content.pm.SigningInfo;
import android.os.Binder;
import android.os.CancellationSignal;
import android.os.IBinder;
@@ -74,12 +75,14 @@ public abstract class AppFunctionService extends Service {
/* context= */ this,
/* onExecuteFunction= */ (platformRequest,
callingPackage,
+ callingPackageSigningInfo,
cancellationSignal,
callback) -> {
AppFunctionService.this.onExecuteFunction(
SidecarConverter.getSidecarExecuteAppFunctionRequest(
platformRequest),
callingPackage,
+ callingPackageSigningInfo,
cancellationSignal,
new OutcomeReceiver<>() {
@Override
@@ -105,15 +108,56 @@ public abstract class AppFunctionService extends Service {
/**
* Called by the system to execute a specific app function.
*
- * <p>This method is triggered when the system requests your AppFunctionService to handle a
- * particular function you have registered and made available.
+ * <p>This method is the entry point for handling all app function requests in an app. When the
+ * system needs your AppFunctionService to perform a function, it will invoke this method.
*
- * <p>To ensure proper routing of function requests, assign a unique identifier to each
- * function. This identifier doesn't need to be globally unique, but it must be unique within
- * your app. For example, a function to order food could be identified as "orderFood". In most
- * cases this identifier should come from the ID automatically generated by the AppFunctions
- * SDK. You can determine the specific function to invoke by calling {@link
- * ExecuteAppFunctionRequest#getFunctionIdentifier()}.
+ * <p>Each function you've registered is identified by a unique identifier. This identifier
+ * doesn't need to be globally unique, but it must be unique within your app. For example, a
+ * function to order food could be identified as "orderFood". In most cases, this identifier is
+ * automatically generated by the AppFunctions SDK.
+ *
+ * <p>You can determine which function to execute by calling {@link
+ * ExecuteAppFunctionRequest#getFunctionIdentifier()}. This allows your service to route the
+ * incoming request to the appropriate logic for handling the specific function.
+ *
+ * <p>This method is always triggered in the main thread. You should run heavy tasks on a worker
+ * thread and dispatch the result with the given callback. You should always report back the
+ * result using the callback, no matter if the execution was successful or not.
+ *
+ * <p>This method also accepts a {@link CancellationSignal} that the app should listen to cancel
+ * the execution of function if requested by the system.
+ *
+ * @param request The function execution request.
+ * @param callingPackage The package name of the app that is requesting the execution.
+ * @param callingPackageSigningInfo The signing information of the app that is requesting the
+ * execution.
+ * @param cancellationSignal A signal to cancel the execution.
+ * @param callback A callback to report back the result or error.
+ */
+ @MainThread
+ public void onExecuteFunction(
+ @NonNull ExecuteAppFunctionRequest request,
+ @NonNull String callingPackage,
+ @NonNull SigningInfo callingPackageSigningInfo,
+ @NonNull CancellationSignal cancellationSignal,
+ @NonNull OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException> callback) {
+ onExecuteFunction(request, callingPackage, cancellationSignal, callback);
+ }
+
+ /**
+ * Called by the system to execute a specific app function.
+ *
+ * <p>This method is the entry point for handling all app function requests in an app. When the
+ * system needs your AppFunctionService to perform a function, it will invoke this method.
+ *
+ * <p>Each function you've registered is identified by a unique identifier. This identifier
+ * doesn't need to be globally unique, but it must be unique within your app. For example, a
+ * function to order food could be identified as "orderFood". In most cases, this identifier is
+ * automatically generated by the AppFunctions SDK.
+ *
+ * <p>You can determine which function to execute by calling {@link
+ * ExecuteAppFunctionRequest#getFunctionIdentifier()}. This allows your service to route the
+ * incoming request to the appropriate logic for handling the specific function.
*
* <p>This method is always triggered in the main thread. You should run heavy tasks on a worker
* thread and dispatch the result with the given callback. You should always report back the
@@ -126,13 +170,14 @@ public abstract class AppFunctionService extends Service {
* @param callingPackage The package name of the app that is requesting the execution.
* @param cancellationSignal A signal to cancel the execution.
* @param callback A callback to report back the result or error.
+ * @deprecated Use {@link #onExecuteFunction(ExecuteAppFunctionRequest, String, SigningInfo,
+ * CancellationSignal, OutcomeReceiver)} instead.
*/
@MainThread
+ @Deprecated
public abstract void onExecuteFunction(
@NonNull ExecuteAppFunctionRequest request,
@NonNull String callingPackage,
@NonNull CancellationSignal cancellationSignal,
- @NonNull
- OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException>
- callback);
+ @NonNull OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException> callback);
}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
index 57d33f1a051e..43764442e2cf 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
@@ -50,7 +50,10 @@ import android.app.appsearch.observer.ObserverSpec;
import android.app.appsearch.observer.SchemaChangeInfo;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.SigningInfo;
import android.os.Binder;
import android.os.CancellationSignal;
import android.os.IBinder;
@@ -292,7 +295,8 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
safeExecuteAppFunctionCallback,
/* bindFlags= */ Context.BIND_AUTO_CREATE
| Context.BIND_FOREGROUND_SERVICE,
- callerBinder);
+ callerBinder,
+ callingUid);
})
.exceptionally(
ex -> {
@@ -444,7 +448,8 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
@NonNull ICancellationSignal cancellationSignalTransport,
@NonNull SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback,
int bindFlags,
- @NonNull IBinder callerBinder) {
+ @NonNull IBinder callerBinder,
+ int callingUid) {
CancellationSignal cancellationSignal =
CancellationSignal.fromTransport(cancellationSignalTransport);
ICancellationCallback cancellationCallback =
@@ -465,7 +470,11 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
new RunAppFunctionServiceCallback(
requestInternal,
cancellationCallback,
- safeExecuteAppFunctionCallback),
+ safeExecuteAppFunctionCallback,
+ getPackageSigningInfo(
+ targetUser,
+ requestInternal.getCallingPackage(),
+ callingUid)),
callerBinder);
if (!bindServiceResult) {
@@ -477,6 +486,23 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
}
}
+ @NonNull
+ private SigningInfo getPackageSigningInfo(
+ @NonNull UserHandle targetUser, @NonNull String packageName, int uid) {
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(targetUser);
+
+ PackageInfo packageInfo;
+ packageInfo =
+ Objects.requireNonNull(
+ mPackageManagerInternal.getPackageInfo(
+ packageName,
+ PackageManager.GET_SIGNING_CERTIFICATES,
+ uid,
+ targetUser.getIdentifier()));
+ return Objects.requireNonNull(packageInfo.signingInfo);
+ }
+
private AppSearchManager getAppSearchManagerAsUser(@NonNull UserHandle userHandle) {
return mContext.createContextAsUser(userHandle, /* flags= */ 0)
.getSystemService(AppSearchManager.class);
diff --git a/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
index 4cba8ecb2092..0cec09dcde8b 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
@@ -23,6 +23,7 @@ import android.app.appfunctions.IAppFunctionService;
import android.app.appfunctions.ICancellationCallback;
import android.app.appfunctions.IExecuteAppFunctionCallback;
import android.app.appfunctions.SafeOneTimeExecuteAppFunctionCallback;
+import android.content.pm.SigningInfo;
import android.os.SystemClock;
import android.util.Slog;
@@ -38,14 +39,17 @@ public class RunAppFunctionServiceCallback implements RunServiceCallCallback<IAp
private final ExecuteAppFunctionAidlRequest mRequestInternal;
private final SafeOneTimeExecuteAppFunctionCallback mSafeExecuteAppFunctionCallback;
private final ICancellationCallback mCancellationCallback;
+ private final SigningInfo mCallerSigningInfo;
public RunAppFunctionServiceCallback(
ExecuteAppFunctionAidlRequest requestInternal,
ICancellationCallback cancellationCallback,
- SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback) {
- this.mRequestInternal = requestInternal;
- this.mSafeExecuteAppFunctionCallback = safeExecuteAppFunctionCallback;
- this.mCancellationCallback = cancellationCallback;
+ SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback,
+ SigningInfo callerSigningInfo) {
+ mRequestInternal = requestInternal;
+ mSafeExecuteAppFunctionCallback = safeExecuteAppFunctionCallback;
+ mCancellationCallback = cancellationCallback;
+ mCallerSigningInfo = callerSigningInfo;
}
@Override
@@ -58,6 +62,7 @@ public class RunAppFunctionServiceCallback implements RunServiceCallCallback<IAp
service.executeAppFunction(
mRequestInternal.getClientRequest(),
mRequestInternal.getCallingPackage(),
+ mCallerSigningInfo,
mCancellationCallback,
new IExecuteAppFunctionCallback.Stub() {
@Override