diff options
5 files changed, 93 insertions, 109 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 861be4079acc..21e77cf4e75c 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -8756,6 +8756,8 @@ package android.app.appfunctions { method public int getResultCode(); method @NonNull public android.app.appsearch.GenericDocument getResultDocument(); method public boolean isSuccess(); + method @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") @NonNull public static android.app.appfunctions.ExecuteAppFunctionResponse newFailure(int, @Nullable String, @Nullable android.os.Bundle); + method @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") @NonNull public static android.app.appfunctions.ExecuteAppFunctionResponse newSuccess(@NonNull android.app.appsearch.GenericDocument, @Nullable android.os.Bundle); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.appfunctions.ExecuteAppFunctionResponse> CREATOR; field public static final String PROPERTY_RETURN_VALUE = "returnValue"; @@ -8767,13 +8769,6 @@ package android.app.appfunctions { field public static final int RESULT_TIMED_OUT = 5; // 0x5 } - @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final class ExecuteAppFunctionResponse.Builder { - ctor public ExecuteAppFunctionResponse.Builder(@NonNull android.app.appsearch.GenericDocument); - ctor public ExecuteAppFunctionResponse.Builder(int, @NonNull String); - method @NonNull public android.app.appfunctions.ExecuteAppFunctionResponse build(); - method @NonNull public android.app.appfunctions.ExecuteAppFunctionResponse.Builder setExtras(@NonNull android.os.Bundle); - } - } package android.app.assist { diff --git a/core/java/android/app/appfunctions/AppFunctionManager.java b/core/java/android/app/appfunctions/AppFunctionManager.java index b6240a79dda8..0ee902632f5f 100644 --- a/core/java/android/app/appfunctions/AppFunctionManager.java +++ b/core/java/android/app/appfunctions/AppFunctionManager.java @@ -50,8 +50,7 @@ public final class AppFunctionManager { * Creates an instance. * * @param mService An interface to the backing service. - * @param context A {@link Context}. - * + * @param context A {@link Context}. * @hide */ public AppFunctionManager(IAppFunctionManager service, Context context) { @@ -108,8 +107,8 @@ public final class AppFunctionManager { } 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()); + callback.accept(ExecuteAppFunctionResponse.newFailure( + getResultCode(e), e.getMessage(), /*extras=*/ null)); } } }); diff --git a/core/java/android/app/appfunctions/AppFunctionService.java b/core/java/android/app/appfunctions/AppFunctionService.java index 6259d165d132..22bc9088f5e4 100644 --- a/core/java/android/app/appfunctions/AppFunctionService.java +++ b/core/java/android/app/appfunctions/AppFunctionService.java @@ -81,8 +81,9 @@ public abstract class AppFunctionService extends Service { // Apps should handle exceptions. But if they don't, report the error on // behalf of them. safeCallback.onResult( - new ExecuteAppFunctionResponse.Builder( - getResultCode(ex), getExceptionMessage(ex)).build()); + ExecuteAppFunctionResponse.newFailure( + getResultCode(ex), + ex.getMessage(), /*extras=*/ null)); } } }; @@ -117,8 +118,4 @@ 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(); - } } diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java index 9fb3375a2446..58d4088f733e 100644 --- a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java +++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java @@ -162,6 +162,55 @@ public final class ExecuteAppFunctionResponse implements Parcelable { } /** + * Returns a successful response. + * + * @param resultDocument The return value of the executed function. + * @param extras The additional metadata data relevant to this function execution + * response. + */ + @NonNull + @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) + public static ExecuteAppFunctionResponse newSuccess(@NonNull GenericDocument resultDocument, + @Nullable Bundle extras) { + Objects.requireNonNull(resultDocument); + Bundle actualExtras = getActualExtras(extras); + GenericDocumentWrapper resultDocumentWrapper = new GenericDocumentWrapper(resultDocument); + + return new ExecuteAppFunctionResponse( + resultDocumentWrapper, actualExtras, RESULT_OK, /*errorMessage=*/null); + } + + /** + * Returns a failure response. + * + * @param resultCode The result code of the app function execution. + * @param extras The additional metadata data relevant to this function execution + * response. + * @param errorMessage The error message associated with the result, if any. + */ + @NonNull + @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) + public static ExecuteAppFunctionResponse newFailure(@ResultCode int resultCode, + @Nullable String errorMessage, + @Nullable Bundle extras) { + if (resultCode == RESULT_OK) { + throw new IllegalArgumentException("resultCode must not be RESULT_OK"); + } + Bundle actualExtras = getActualExtras(extras); + GenericDocumentWrapper emptyWrapper = new GenericDocumentWrapper( + new GenericDocument.Builder<>("", "", "").build()); + return new ExecuteAppFunctionResponse( + emptyWrapper, actualExtras, resultCode, errorMessage); + } + + private static Bundle getActualExtras(@Nullable Bundle extras) { + if (extras == null) { + return Bundle.EMPTY; + } + return extras; + } + + /** * Returns a generic document containing the return value of the executed function. * * <p>The {@link #PROPERTY_RETURN_VALUE} key can be used to obtain the return value.</p> @@ -250,64 +299,4 @@ public final class ExecuteAppFunctionResponse implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface ResultCode { } - - /** - * The builder for creating {@link ExecuteAppFunctionResponse} instances. - */ - @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) - public static final class Builder { - @NonNull - private GenericDocument mResultDocument = - new GenericDocument.Builder<>("", "", "").build(); - @NonNull - private Bundle mExtras = Bundle.EMPTY; - private int mResultCode; - @Nullable - private String mErrorMessage; - - /** - * Creates a new builder for {@link ExecuteAppFunctionResponse}. - */ - private Builder() { - } - - /** - * Creates a new builder for {@link ExecuteAppFunctionResponse} to build a success response - * with a result code of {@link #RESULT_OK} and a resultDocument. - */ - public Builder(@NonNull GenericDocument resultDocument) { - Objects.requireNonNull(resultDocument); - mResultDocument = resultDocument; - mResultCode = RESULT_OK; - } - - /** - * Creates a new builder for {@link ExecuteAppFunctionResponse} to build an error response - * with a result code and an error message. - */ - public Builder(@ResultCode int resultCode, - @NonNull String errorMessage) { - mResultCode = resultCode; - mErrorMessage = Objects.requireNonNull(errorMessage); - } - - /** - * Sets the extras of the app function execution. - */ - @NonNull - public Builder setExtras(@NonNull Bundle extras) { - mExtras = Objects.requireNonNull(extras); - return this; - } - - /** - * Builds the {@link ExecuteAppFunctionResponse} instance. - */ - @NonNull - public ExecuteAppFunctionResponse build() { - return new ExecuteAppFunctionResponse( - new GenericDocumentWrapper(mResultDocument), - mExtras, mResultCode, mErrorMessage); - } - } } diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java index 53885fc5799e..f5d07ef850c8 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java +++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java @@ -94,36 +94,39 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { targetUser = mCallerValidator.verifyTargetUserHandle( requestInternal.getUserHandle(), validatedCallingPackage); } catch (SecurityException exception) { - safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse - .Builder(ExecuteAppFunctionResponse.RESULT_DENIED, - getExceptionMessage(exception)).build()); + safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse + .newFailure(ExecuteAppFunctionResponse.RESULT_DENIED, + exception.getMessage(), + /*extras=*/ null)); return; } // TODO(b/354956319): Add and honor the new enterprise policies. if (mCallerValidator.isUserOrganizationManaged(targetUser)) { - safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse.Builder( + safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure( ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR, - "Cannot run on a device with a device owner or from the managed profile." - ).build()); + "Cannot run on a device with a device owner or from the managed profile.", + /*extras=*/ null + )); return; } String targetPackageName = requestInternal.getClientRequest().getTargetPackageName(); if (TextUtils.isEmpty(targetPackageName)) { - safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse.Builder( + safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure( ExecuteAppFunctionResponse.RESULT_INVALID_ARGUMENT, - "Target package name cannot be empty." - ).build()); + "Target package name cannot be empty.", + /*extras=*/ null + )); return; } if (!mCallerValidator.verifyCallerCanExecuteAppFunction( validatedCallingPackage, targetPackageName)) { - safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse - .Builder(ExecuteAppFunctionResponse.RESULT_DENIED, - "Caller does not have permission to execute the appfunction") - .build()); + safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse + .newFailure(ExecuteAppFunctionResponse.RESULT_DENIED, + "Caller does not have permission to execute the appfunction", + /*extras=*/ null)); return; } @@ -131,10 +134,11 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { targetPackageName, targetUser); if (serviceIntent == null) { - safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse.Builder( + safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure( ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR, - "Cannot find the target service." - ).build()); + "Cannot find the target service.", + /*extras=*/ null + )); return; } bindAppFunctionServiceUnchecked(requestInternal, serviceIntent, targetUser, @@ -171,9 +175,10 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { } ); } catch (Exception e) { - safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse - .Builder(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR, - getExceptionMessage(e)).build()); + safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse + .newFailure(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR, + e.getMessage(), + /*extras=*/ null)); serviceUsageCompleteListener.onCompleted(); } } @@ -181,33 +186,32 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { @Override public void onFailedToConnect() { Slog.e(TAG, "Failed to connect to service"); - safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse - .Builder(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR, - "Failed to connect to AppFunctionService").build()); + safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse + .newFailure(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR, + "Failed to connect to AppFunctionService", + /*extras=*/ null)); } @Override public void onTimedOut() { Slog.e(TAG, "Timed out"); safeExecuteAppFunctionCallback.onResult( - new ExecuteAppFunctionResponse.Builder( + ExecuteAppFunctionResponse.newFailure( ExecuteAppFunctionResponse.RESULT_TIMED_OUT, - "Binding to AppFunctionService timed out." - ).build()); + "Binding to AppFunctionService timed out.", + /*extras=*/ null + )); } } ); if (!bindServiceResult) { Slog.e(TAG, "Failed to bind to the AppFunctionService"); - safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse.Builder( + safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure( ExecuteAppFunctionResponse.RESULT_TIMED_OUT, - "Failed to bind the AppFunctionService." - ).build()); + "Failed to bind the AppFunctionService.", + /*extras=*/ null + )); } } - - private String getExceptionMessage(Exception exception) { - return exception.getMessage() == null ? "" : exception.getMessage(); - } } |