Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -8722,6 +8722,7 @@ package android.app.admin { package android.app.appfunctions { @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class AppFunctionManager { method @RequiresPermission(anyOf={"android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED", "android.permission.EXECUTE_APP_FUNCTIONS"}, conditional=true) public void executeAppFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appfunctions.ExecuteAppFunctionResponse>); } @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public abstract class AppFunctionService extends android.app.Service { core/java/android/app/appfunctions/AppFunctionManager.java +75 −1 Original line number Diff line number Diff line Loading @@ -16,11 +16,22 @@ package android.app.appfunctions; import static android.app.appfunctions.ExecuteAppFunctionResponse.getResultCode; import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.UserHandleAware; import android.content.Context; import android.os.RemoteException; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * Provides app functions related functionalities. Loading @@ -28,6 +39,7 @@ import android.content.Context; * <p>App function is a specific piece of functionality that an app offers to the system. These * functionalities can be integrated into various system features. */ // TODO(b/357551503): Implement get and set enabled app function APIs. @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) @SystemService(Context.APP_FUNCTION_SERVICE) public final class AppFunctionManager { Loading @@ -35,7 +47,10 @@ public final class AppFunctionManager { private final Context mContext; /** * TODO(b/357551503): add comments when implement this class * Creates an instance. * * @param mService An interface to the backing service. * @param context A {@link Context}. * * @hide */ Loading @@ -43,4 +58,63 @@ public final class AppFunctionManager { this.mService = mService; this.mContext = context; } /** * Executes the app function. * <p> * Note: Applications can execute functions they define. To execute functions defined in * another component, apps would need to have * {@code android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or * {@code android.permission.EXECUTE_APP_FUNCTIONS}. * * @param request the request to execute the app function * @param executor the executor to run the callback * @param callback the callback to receive the function execution result. if the calling app * does not own the app function or does not have {@code * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@code * android.permission.EXECUTE_APP_FUNCTIONS}, the execution result will contain * {@code ExecuteAppFunctionResponse.RESULT_DENIED}. */ // TODO(b/360864791): Document that apps can opt-out from being executed by callers with // EXECUTE_APP_FUNCTIONS and how a caller knows whether a function is opted out. // TODO(b/357551503): Update documentation when get / set APIs are implemented that this will // also return RESULT_DENIED if the app function is disabled. @RequiresPermission( anyOf = {Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED, Manifest.permission.EXECUTE_APP_FUNCTIONS}, conditional = true) @UserHandleAware public void executeAppFunction( @NonNull ExecuteAppFunctionRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<ExecuteAppFunctionResponse> callback ) { Objects.requireNonNull(request); Objects.requireNonNull(executor); Objects.requireNonNull(callback); ExecuteAppFunctionAidlRequest aidlRequest = new ExecuteAppFunctionAidlRequest( request, mContext.getUser(), mContext.getPackageName()); try { mService.executeAppFunction( aidlRequest, new IExecuteAppFunctionCallback.Stub() { @Override public void onResult(ExecuteAppFunctionResponse result) { try { executor.execute(() -> callback.accept(result)); } catch (RuntimeException e) { // Ideally shouldn't happen since errors are wrapped into the // response, but we catch it here for additional safety. callback.accept(new ExecuteAppFunctionResponse.Builder( getResultCode(e), e.getMessage()).build()); } } }); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } } core/java/android/app/appfunctions/AppFunctionService.java +8 −10 Original line number Diff line number Diff line Loading @@ -16,9 +16,10 @@ package android.app.appfunctions; import static android.Manifest.permission.BIND_APP_FUNCTION_SERVICE; import static android.app.appfunctions.ExecuteAppFunctionResponse.getResultCode; import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.Manifest.permission.BIND_APP_FUNCTION_SERVICE; import android.annotation.FlaggedApi; import android.annotation.MainThread; Loading Loading @@ -81,18 +82,11 @@ public abstract class AppFunctionService extends Service { // behalf of them. safeCallback.onResult( new ExecuteAppFunctionResponse.Builder( getResultCode(ex), ex.getMessage()).build()); getResultCode(ex), getExceptionMessage(ex)).build()); } } }; private static int getResultCode(@NonNull Throwable t) { if (t instanceof IllegalArgumentException) { return ExecuteAppFunctionResponse.RESULT_INVALID_ARGUMENT; } return ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR; } @NonNull @Override public final IBinder onBind(@Nullable Intent intent) { Loading Loading @@ -123,4 +117,8 @@ public abstract class AppFunctionService extends Service { public abstract void onExecuteFunction( @NonNull ExecuteAppFunctionRequest request, @NonNull Consumer<ExecuteAppFunctionResponse> callback); private String getExceptionMessage(Exception exception) { return exception.getMessage() == null ? "" : exception.getMessage(); } } core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java +12 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,18 @@ public final class ExecuteAppFunctionResponse implements Parcelable { public @interface ResultCode { } /** * Returns result codes from throwable. * * @hide */ static @ResultCode int getResultCode(@NonNull Throwable t) { if (t instanceof IllegalArgumentException) { return ExecuteAppFunctionResponse.RESULT_INVALID_ARGUMENT; } return ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR; } /** * The builder for creating {@link ExecuteAppFunctionResponse} instances. */ Loading core/java/android/app/appfunctions/IAppFunctionManager.aidl +5 −4 Original line number Diff line number Diff line Loading @@ -20,10 +20,11 @@ import android.app.appfunctions.ExecuteAppFunctionAidlRequest; import android.app.appfunctions.IExecuteAppFunctionCallback; /** * Interface between an app and the server implementation service (AppFunctionManagerService). * Defines the interface for apps to interact with the app function execution service * {@code AppFunctionManagerService} running in the system server process. * @hide */ oneway interface IAppFunctionManager { interface IAppFunctionManager { /** * Executes an app function provided by {@link AppFunctionService} through the system. * Loading Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -8722,6 +8722,7 @@ package android.app.admin { package android.app.appfunctions { @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class AppFunctionManager { method @RequiresPermission(anyOf={"android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED", "android.permission.EXECUTE_APP_FUNCTIONS"}, conditional=true) public void executeAppFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appfunctions.ExecuteAppFunctionResponse>); } @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public abstract class AppFunctionService extends android.app.Service {
core/java/android/app/appfunctions/AppFunctionManager.java +75 −1 Original line number Diff line number Diff line Loading @@ -16,11 +16,22 @@ package android.app.appfunctions; import static android.app.appfunctions.ExecuteAppFunctionResponse.getResultCode; import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.UserHandleAware; import android.content.Context; import android.os.RemoteException; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * Provides app functions related functionalities. Loading @@ -28,6 +39,7 @@ import android.content.Context; * <p>App function is a specific piece of functionality that an app offers to the system. These * functionalities can be integrated into various system features. */ // TODO(b/357551503): Implement get and set enabled app function APIs. @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) @SystemService(Context.APP_FUNCTION_SERVICE) public final class AppFunctionManager { Loading @@ -35,7 +47,10 @@ public final class AppFunctionManager { private final Context mContext; /** * TODO(b/357551503): add comments when implement this class * Creates an instance. * * @param mService An interface to the backing service. * @param context A {@link Context}. * * @hide */ Loading @@ -43,4 +58,63 @@ public final class AppFunctionManager { this.mService = mService; this.mContext = context; } /** * Executes the app function. * <p> * Note: Applications can execute functions they define. To execute functions defined in * another component, apps would need to have * {@code android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or * {@code android.permission.EXECUTE_APP_FUNCTIONS}. * * @param request the request to execute the app function * @param executor the executor to run the callback * @param callback the callback to receive the function execution result. if the calling app * does not own the app function or does not have {@code * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@code * android.permission.EXECUTE_APP_FUNCTIONS}, the execution result will contain * {@code ExecuteAppFunctionResponse.RESULT_DENIED}. */ // TODO(b/360864791): Document that apps can opt-out from being executed by callers with // EXECUTE_APP_FUNCTIONS and how a caller knows whether a function is opted out. // TODO(b/357551503): Update documentation when get / set APIs are implemented that this will // also return RESULT_DENIED if the app function is disabled. @RequiresPermission( anyOf = {Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED, Manifest.permission.EXECUTE_APP_FUNCTIONS}, conditional = true) @UserHandleAware public void executeAppFunction( @NonNull ExecuteAppFunctionRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<ExecuteAppFunctionResponse> callback ) { Objects.requireNonNull(request); Objects.requireNonNull(executor); Objects.requireNonNull(callback); ExecuteAppFunctionAidlRequest aidlRequest = new ExecuteAppFunctionAidlRequest( request, mContext.getUser(), mContext.getPackageName()); try { mService.executeAppFunction( aidlRequest, new IExecuteAppFunctionCallback.Stub() { @Override public void onResult(ExecuteAppFunctionResponse result) { try { executor.execute(() -> callback.accept(result)); } catch (RuntimeException e) { // Ideally shouldn't happen since errors are wrapped into the // response, but we catch it here for additional safety. callback.accept(new ExecuteAppFunctionResponse.Builder( getResultCode(e), e.getMessage()).build()); } } }); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } }
core/java/android/app/appfunctions/AppFunctionService.java +8 −10 Original line number Diff line number Diff line Loading @@ -16,9 +16,10 @@ package android.app.appfunctions; import static android.Manifest.permission.BIND_APP_FUNCTION_SERVICE; import static android.app.appfunctions.ExecuteAppFunctionResponse.getResultCode; import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.Manifest.permission.BIND_APP_FUNCTION_SERVICE; import android.annotation.FlaggedApi; import android.annotation.MainThread; Loading Loading @@ -81,18 +82,11 @@ public abstract class AppFunctionService extends Service { // behalf of them. safeCallback.onResult( new ExecuteAppFunctionResponse.Builder( getResultCode(ex), ex.getMessage()).build()); getResultCode(ex), getExceptionMessage(ex)).build()); } } }; private static int getResultCode(@NonNull Throwable t) { if (t instanceof IllegalArgumentException) { return ExecuteAppFunctionResponse.RESULT_INVALID_ARGUMENT; } return ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR; } @NonNull @Override public final IBinder onBind(@Nullable Intent intent) { Loading Loading @@ -123,4 +117,8 @@ public abstract class AppFunctionService extends Service { public abstract void onExecuteFunction( @NonNull ExecuteAppFunctionRequest request, @NonNull Consumer<ExecuteAppFunctionResponse> callback); private String getExceptionMessage(Exception exception) { return exception.getMessage() == null ? "" : exception.getMessage(); } }
core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java +12 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,18 @@ public final class ExecuteAppFunctionResponse implements Parcelable { public @interface ResultCode { } /** * Returns result codes from throwable. * * @hide */ static @ResultCode int getResultCode(@NonNull Throwable t) { if (t instanceof IllegalArgumentException) { return ExecuteAppFunctionResponse.RESULT_INVALID_ARGUMENT; } return ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR; } /** * The builder for creating {@link ExecuteAppFunctionResponse} instances. */ Loading
core/java/android/app/appfunctions/IAppFunctionManager.aidl +5 −4 Original line number Diff line number Diff line Loading @@ -20,10 +20,11 @@ import android.app.appfunctions.ExecuteAppFunctionAidlRequest; import android.app.appfunctions.IExecuteAppFunctionCallback; /** * Interface between an app and the server implementation service (AppFunctionManagerService). * Defines the interface for apps to interact with the app function execution service * {@code AppFunctionManagerService} running in the system server process. * @hide */ oneway interface IAppFunctionManager { interface IAppFunctionManager { /** * Executes an app function provided by {@link AppFunctionService} through the system. * Loading