diff options
author | 2024-12-29 21:44:52 +0000 | |
---|---|---|
committer | 2025-01-07 12:23:11 +0000 | |
commit | 14e446faae0127eefc6c898a1b039834c126f6c6 (patch) | |
tree | 4fb2732615629e9728819720e3217fdb42f98bfa | |
parent | a39afd3f941b6b8aed971a0367e740b7840cc4ff (diff) |
Provide caller signingInfo on execute app function
Flag: android.app.appfunctions.flags.enable_app_function_manager
Test: Will Update CTS
Bug: 386324561
Change-Id: Ia6929eca9342d0abf180b6b8b7e46f4c3baf176e
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 |